3
0
Fork 0
forked from mirrors/linux

pci-v6.16-changes

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCgAyFiEEgMe7l+5h9hnxdsnuWYigwDrT+vwFAmhAa9EUHGJoZWxnYWFz
 QGdvb2dsZS5jb20ACgkQWYigwDrT+vyA3w//aX8d73z/xVxkYLMN/6XQA5fdmd4d
 Dv4n0Pjf0WCMKbsgRCdXEYLvcHV8VhH5iCR/b2UsFm9LjxSIRuqE5XosY3bNhrHn
 xVKEh2prq2XZOibWrFkJ+RZ0FF7Ogq1Uy5gUBbBHbE1q1byZzrOALaF3FWGaDIZQ
 6QLLAFtd3UtqOOUu8J8P9N15uFR8gunyfuM9U7TLMcy4B8txk6T6m/9xAWtRURuJ
 I6WN8lO+g8Nl2mL9m27+wyWiVT3tKqoMwp8rVtym/L5JQOmHycYhn0WQAr2dPCMs
 Xbgmoeei0je7mZvk5btpt68NAKQ3ZnCVkxbbINBkUxAjI0dbI6h37EhW18ShYVUk
 CCo4fmaFtwP8qNN9tSvDN8vZdGB44fN5tIz4lmGzKk5gt+oV50RC/APrzC+PJBQ0
 +2SdDVKj71Gr2H1VnI6uLB7oQ+tp7TOdhg+DGV4bdc6QFnsM+BpKWRq5f1UQcau/
 XVDmorM/2t6z0DNktAv3NFwSodUjk1loWESr/pRBH1AqAWZTK98PWIg97XYsal59
 zbJ3dLrnCqUNozeVgjtZo1LWD2FZaVTvhq2NY7D+QPpnMGhFUhHxNliZUXiQa1q4
 boI2hEFdu3IQP/OC2a1zGJyMRLU43d5rhZ1U5xQSVtM0c3lgCY7rn/t26LymQVPA
 SYdg2jBcnhe6gXo=
 =eWJw
 -----END PGP SIGNATURE-----

Merge tag 'pci-v6.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci

Pull pci updates from Bjorn Helgaas:
 "Enumeration:

   - Print the actual delay time in pci_bridge_wait_for_secondary_bus()
     instead of assuming it was 1000ms (Wilfred Mallawa)

   - Revert 'iommu/amd: Prevent binding other PCI drivers to IOMMU PCI
     devices', which broke resume from system sleep on AMD platforms and
     has been fixed by other commits (Lukas Wunner)

  Resource management:

   - Remove mtip32xx use of pcim_iounmap_regions(), which is deprecated
     and unnecessary (Philipp Stanner)

   - Remove pcim_iounmap_regions() and pcim_request_region_exclusive()
     and related flags since all uses have been removed (Philipp
     Stanner)

   - Rework devres 'request' functions so they are no longer 'hybrid',
     i.e., their behavior no longer depends on whether
     pcim_enable_device or pci_enable_device() was used, and remove
     related code (Philipp Stanner)

   - Warn (not BUG()) about failure to assign optional resources (Ilpo
     Järvinen)

  Error handling:

   - Log the DPC Error Source ID only when it's actually valid (when
     ERR_FATAL or ERR_NONFATAL was received from a downstream device)
     and decode into bus/device/function (Bjorn Helgaas)

   - Determine AER log level once and save it so all related messages
     use the same level (Karolina Stolarek)

   - Use KERN_WARNING, not KERN_ERR, when logging PCIe Correctable
     Errors (Karolina Stolarek)

   - Ratelimit PCIe Correctable and Non-Fatal error logging, with sysfs
     controls on interval and burst count, to avoid flooding logs and
     RCU stall warnings (Jon Pan-Doh)

  Power management:

   - Increment PM usage counter when probing reset methods so we don't
     try to read config space of a powered-off device (Alex Williamson)

   - Set all devices to D0 during enumeration to ensure ACPI opregion is
     connected via _REG (Mario Limonciello)

  Power control:

   - Rename pwrctrl Kconfig symbols from 'PWRCTL' to 'PWRCTRL' to match
     the filename paths. Retain old deprecated symbols for
     compatibility, except for the pwrctrl slot driver
     (PCI_PWRCTRL_SLOT) (Johan Hovold)

   - When unregistering pwrctrl, cancel outstanding rescan work before
     cleaning up data structures to avoid use-after-free issues (Brian
     Norris)

  Bandwidth control:

   - Simplify link bandwidth controller by replacing the count of Link
     Bandwidth Management Status (LBMS) events with a PCI_LINK_LBMS_SEEN
     flag (Ilpo Järvinen)

   - Update the Link Speed after retraining, since the Link Speed may
     have changed (Ilpo Järvinen)

  PCIe native device hotplug:

   - Ignore Presence Detect Changed caused by DPC.

     pciehp already ignores Link Down/Up events caused by DPC, but on
     slots using in-band presence detect, DPC causes a spurious Presence
     Detect Changed event (Lukas Wunner)

   - Ignore Link Down/Up caused by Secondary Bus Reset.

     On hotplug ports using in-band presence detect, the reset causes a
     Presence Detect Changed event, which mistakenly caused teardown and
     re-enumeration of the device. Drivers may need to annotate code
     that resets their device (Lukas Wunner)

  Virtualization:

   - Add an ACS quirk for Loongson Root Ports that don't advertise ACS
     but don't allow peer-to-peer transactions between Root Ports; the
     quirk allows each Root Port to be in a separate IOMMU group (Huacai
     Chen)

  Endpoint framework:

   - For fixed-size BARs, retain both the actual size and the possibly
     larger size allocated to accommodate iATU alignment requirements
     (Jerome Brunet)

   - Simplify ctrl/SPAD space allocation and avoid allocating more space
     than needed (Jerome Brunet)

   - Correct MSI-X PBA offset calculations for DesignWare and Cadence
     endpoint controllers (Niklas Cassel)

   - Align the return value (number of interrupts) encoding for
     pci_epc_get_msi()/pci_epc_ops::get_msi() and
     pci_epc_get_msix()/pci_epc_ops::get_msix() (Niklas Cassel)

   - Align the nr_irqs parameter encoding for
     pci_epc_set_msi()/pci_epc_ops::set_msi() and
     pci_epc_set_msix()/pci_epc_ops::set_msix() (Niklas Cassel)

  Common host controller library:

   - Convert pci-host-common to a library so platforms that don't need
     native host controller drivers don't need to include these helper
     functions (Manivannan Sadhasivam)

  Apple PCIe controller driver:

   - Extract ECAM bridge creation helper from pci_host_common_probe() to
     separate driver-specific things like MSI from PCI things (Marc
     Zyngier)

   - Dynamically allocate RID-to_SID bitmap to prepare for SoCs with
     varying capabilities (Marc Zyngier)

   - Skip ports disabled in DT when setting up ports (Janne Grunau)

   - Add t6020 compatible string (Alyssa Rosenzweig)

   - Add T602x PCIe support (Hector Martin)

   - Directly set/clear INTx mask bits because T602x dropped the
     accessors that could do this without locking (Marc Zyngier)

   - Move port PHY registers to their own reg items to accommodate
     T602x, which moves them around; retain default offsets for existing
     DTs that lack phy%d entries with the reg offsets (Hector Martin)

   - Stop polling for core refclk, which doesn't work on T602x and the
     bootloader has already done anyway (Hector Martin)

   - Use gpiod_set_value_cansleep() when asserting PERST# in probe
     because we're allowed to sleep there (Hector Martin)

  Cadence PCIe controller driver:

   - Drop a runtime PM 'put' to resolve a runtime atomic count underflow
     (Hans Zhang)

   - Make the cadence core buildable as a module (Kishon Vijay Abraham I)

   - Add cdns_pcie_host_disable() and cdns_pcie_ep_disable() for use by
     loadable drivers when they are removed (Siddharth Vadapalli)

  Freescale i.MX6 PCIe controller driver:

   - Apply link training workaround only on IMX6Q, IMX6SX, IMX6SP
     (Richard Zhu)

   - Remove redundant dw_pcie_wait_for_link() from
     imx_pcie_start_link(); since the DWC core does this, imx6 only
     needs it when retraining for a faster link speed (Richard Zhu)

   - Toggle i.MX95 core reset to align with PHY powerup (Richard Zhu)

   - Set SYS_AUX_PWR_DET to work around i.MX95 ERR051624 erratum: in
     some cases, the controller can't exit 'L23 Ready' through Beacon or
     PERST# deassertion (Richard Zhu)

   - Clear GEN3_ZRXDC_NONCOMPL to work around i.MX95 ERR051586 erratum:
     controller can't meet 2.5 GT/s ZRX-DC timing when operating at 8
     GT/s, causing timeouts in L1 (Richard Zhu)

   - Wait for i.MX95 PLL lock before enabling controller (Richard Zhu)

   - Save/restore i.MX95 LUT for suspend/resume (Richard Zhu)

  Mobiveil PCIe controller driver:

   - Return bool (not int) for link-up check in
     mobiveil_pab_ops.link_up() and layerscape-gen4, mobiveil (Hans
     Zhang)

  NVIDIA Tegra194 PCIe controller driver:

   - Create debugfs directory for 'aspm_state_cnt' only when
     CONFIG_PCIEASPM is enabled, since there are no other entries (Hans
     Zhang)

  Qualcomm PCIe controller driver:

   - Add OF support for parsing DT 'eq-presets-<N>gts' property for lane
     equalization presets (Krishna Chaitanya Chundru)

   - Read Maximum Link Width from the Link Capabilities register if DT
     lacks 'num-lanes' property (Krishna Chaitanya Chundru)

   - Add Physical Layer 64 GT/s Capability ID and register offsets for
     8, 32, and 64 GT/s lane equalization registers (Krishna Chaitanya
     Chundru)

   - Add generic dwc support for configuring lane equalization presets
     (Krishna Chaitanya Chundru)

   - Add DT and driver support for PCIe on IPQ5018 SoC (Nitheesh Sekar)

  Renesas R-Car PCIe controller driver:

   - Describe endpoint BAR 4 as being fixed size (Jerome Brunet)

   - Document how to obtain R-Car V4H (r8a779g0) controller firmware
     (Yoshihiro Shimoda)

  Rockchip PCIe controller driver:

   - Reorder rockchip_pci_core_rsts because
     reset_control_bulk_deassert() deasserts in reverse order, to fix a
     link training regression (Jensen Huang)

   - Mark RK3399 as being capable of raising INTx interrupts (Niklas
     Cassel)

  Rockchip DesignWare PCIe controller driver:

   - Check only PCIE_LINKUP, not LTSSM status, to determine whether the
     link is up (Shawn Lin)

   - Increase N_FTS (used in L0s->L0 transitions) and enable ASPM L0s
     for Root Complex and Endpoint modes (Shawn Lin)

   - Hide the broken ATS Capability in rockchip_pcie_ep_init() instead
     of rockchip_pcie_ep_pre_init() so it stays hidden after PERST#
     resets non-sticky registers (Shawn Lin)

   - Call phy_power_off() before phy_exit() in rockchip_pcie_phy_deinit()
     (Diederik de Haas)

  Synopsys DesignWare PCIe controller driver:

   - Set PORT_LOGIC_LINK_WIDTH to one lane to make initial link training
     more robust; this will not affect the intended link width if all
     lanes are functional (Wenbin Yao)

   - Return bool (not int) for link-up check in dw_pcie_ops.link_up()
     and armada8k, dra7xx, dw-rockchip, exynos, histb, keembay,
     keystone, kirin, meson, qcom, qcom-ep, rcar_gen4, spear13xx,
     tegra194, uniphier, visconti (Hans Zhang)

   - Add debugfs support for exposing DWC device-specific PTM context
     (Manivannan Sadhasivam)

  TI J721E PCIe driver:

   - Make j721e buildable as a loadable and removable module (Siddharth
     Vadapalli)

   - Fix j721e host/endpoint dependencies that result in link failures
     in some configs (Arnd Bergmann)

  Device tree bindings:

   - Add qcom DT binding for 'global' interrupt (PCIe controller and
     link-specific events) for ipq8074, ipq8074-gen3, ipq6018, sa8775p,
     sc7280, sc8180x sdm845, sm8150, sm8250, sm8350 (Manivannan
     Sadhasivam)

   - Add qcom DT binding for 8 MSI SPI interrupts for msm8998, ipq8074,
     ipq8074-gen3, ipq6018 (Manivannan Sadhasivam)

   - Add dw rockchip DT binding for rk3576 and rk3562 (Kever Yang)

   - Correct indentation and style of examples in brcm,stb-pcie,
     cdns,cdns-pcie-ep, intel,keembay-pcie-ep, intel,keembay-pcie,
     microchip,pcie-host, rcar-pci-ep, rcar-pci-host, xilinx-versal-cpm
     (Krzysztof Kozlowski)

   - Convert Marvell EBU (dove, kirkwood, armada-370, armada-xp) and
     armada8k from text to schema DT bindings (Rob Herring)

   - Remove obsolete .txt DT bindings for content that has been moved to
     schemas (Rob Herring)

   - Add qcom DT binding for MHI registers in IPQ5332, IPQ6018, IPQ8074
     and IPQ9574 (Varadarajan Narayanan)

   - Convert v3,v360epc-pci from text to DT schema binding (Rob Herring)

   - Change microchip,pcie-host DT binding to be 'dma-noncoherent' since
     PolarFire may be configured that way (Conor Dooley)

  Miscellaneous:

   - Drop 'pci' suffix from intel_mid_pci.c filename to match similar
     files (Andy Shevchenko)

   - All platforms with PCI have an MMU, so add PCI Kconfig dependency
     on MMU to simplify build testing and avoid inadvertent build
     regressions (Arnd Bergmann)

   - Update Krzysztof Wilczyński's email address in MAINTAINERS
     (Krzysztof Wilczyński)

   - Update Manivannan Sadhasivam's email address in MAINTAINERS
     (Manivannan Sadhasivam)"

* tag 'pci-v6.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: (147 commits)
  MAINTAINERS: Update Manivannan Sadhasivam email address
  PCI: j721e: Fix host/endpoint dependencies
  PCI: j721e: Add support to build as a loadable module
  PCI: cadence-ep: Introduce cdns_pcie_ep_disable() helper for cleanup
  PCI: cadence-host: Introduce cdns_pcie_host_disable() helper for cleanup
  PCI: cadence: Add support to build pcie-cadence library as a kernel module
  MAINTAINERS: Update Krzysztof Wilczyński email address
  PCI: Remove unnecessary linesplit in __pci_setup_bridge()
  PCI: WARN (not BUG()) when we fail to assign optional resources
  PCI: Remove unused pci_printk()
  PCI: qcom: Replace PERST# sleep time with proper macro
  PCI: dw-rockchip: Replace PERST# sleep time with proper macro
  PCI: host-common: Convert to library for host controller drivers
  PCI/ERR: Remove misleading TODO regarding kernel panic
  PCI: cadence: Remove duplicate message code definitions
  PCI: endpoint: Align pci_epc_set_msix(), pci_epc_ops::set_msix() nr_irqs encoding
  PCI: endpoint: Align pci_epc_set_msi(), pci_epc_ops::set_msi() nr_irqs encoding
  PCI: endpoint: Align pci_epc_get_msix(), pci_epc_ops::get_msix() return value encoding
  PCI: endpoint: Align pci_epc_get_msi(), pci_epc_ops::get_msi() return value encoding
  PCI: cadence-ep: Correct PBA offset in .set_msix() callback
  ...
This commit is contained in:
Linus Torvalds 2025-06-04 11:26:17 -07:00
commit 3719a04a80
148 changed files with 3401 additions and 2220 deletions

View file

@ -419,6 +419,8 @@ Krishna Manikandan <quic_mkrishn@quicinc.com> <mkrishn@codeaurora.org>
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski.k@gmail.com>
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
Krzysztof Kozlowski <krzk@kernel.org> <krzysztof.kozlowski@canonical.com>
Krzysztof Wilczyński <kwilczynski@kernel.org> <krzysztof.wilczynski@linux.com>
Krzysztof Wilczyński <kwilczynski@kernel.org> <kw@linux.com>
Kshitiz Godara <quic_kgodara@quicinc.com> <kgodara@codeaurora.org>
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org>
@ -461,6 +463,7 @@ Maheshwar Ajja <quic_majja@quicinc.com> <majja@codeaurora.org>
Malathi Gottam <quic_mgottam@quicinc.com> <mgottam@codeaurora.org>
Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org>
Manivannan Sadhasivam <mani@kernel.org> <manivannanece23@gmail.com>
Manivannan Sadhasivam <mani@kernel.org> <manivannan.sadhasivam@linaro.org>
Manoj Basapathi <quic_manojbm@quicinc.com> <manojbm@codeaurora.org>
Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>

View file

@ -0,0 +1,70 @@
What: /sys/kernel/debug/pcie_ptm_*/local_clock
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM local clock in nanoseconds. Applicable for both Root
Complex and Endpoint controllers.
What: /sys/kernel/debug/pcie_ptm_*/master_clock
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM master clock in nanoseconds. Applicable only for
Endpoint controllers.
What: /sys/kernel/debug/pcie_ptm_*/t1
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM T1 timestamp in nanoseconds. Applicable only for
Endpoint controllers.
What: /sys/kernel/debug/pcie_ptm_*/t2
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM T2 timestamp in nanoseconds. Applicable only for
Root Complex controllers.
What: /sys/kernel/debug/pcie_ptm_*/t3
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM T3 timestamp in nanoseconds. Applicable only for
Root Complex controllers.
What: /sys/kernel/debug/pcie_ptm_*/t4
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RO) PTM T4 timestamp in nanoseconds. Applicable only for
Endpoint controllers.
What: /sys/kernel/debug/pcie_ptm_*/context_update
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RW) Control the PTM context update mode. Applicable only for
Endpoint controllers.
Following values are supported:
* auto = PTM context auto update trigger for every 10ms
* manual = PTM context manual update. Writing 'manual' to this
file triggers PTM context update (default)
What: /sys/kernel/debug/pcie_ptm_*/context_valid
Date: May 2025
Contact: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Description:
(RW) Control the PTM context validity (local clock timing).
Applicable only for Root Complex controllers. PTM context is
invalidated by hardware if the Root Complex enters low power
mode or changes link frequency.
Following values are supported:
* 0 = PTM context invalid (default)
* 1 = PTM context valid

View file

@ -117,3 +117,47 @@ Date: July 2018
KernelVersion: 4.19.0
Contact: linux-pci@vger.kernel.org, rajatja@google.com
Description: Total number of ERR_NONFATAL messages reported to rootport.
PCIe AER ratelimits
-------------------
These attributes show up under all the devices that are AER capable.
They represent configurable ratelimits of logs per error type.
See Documentation/PCI/pcieaer-howto.rst for more info on ratelimits.
What: /sys/bus/pci/devices/<dev>/aer/correctable_ratelimit_interval_ms
Date: May 2025
KernelVersion: 6.16.0
Contact: linux-pci@vger.kernel.org
Description: Writing 0 disables AER correctable error log ratelimiting.
Writing a positive value sets the ratelimit interval in ms.
Default is DEFAULT_RATELIMIT_INTERVAL (5000 ms).
What: /sys/bus/pci/devices/<dev>/aer/correctable_ratelimit_burst
Date: May 2025
KernelVersion: 6.16.0
Contact: linux-pci@vger.kernel.org
Description: Ratelimit burst for correctable error logs. Writing a value
changes the number of errors (burst) allowed per interval
before ratelimiting. Reading gets the current ratelimit
burst. Default is DEFAULT_RATELIMIT_BURST (10).
What: /sys/bus/pci/devices/<dev>/aer/nonfatal_ratelimit_interval_ms
Date: May 2025
KernelVersion: 6.16.0
Contact: linux-pci@vger.kernel.org
Description: Writing 0 disables AER non-fatal uncorrectable error log
ratelimiting. Writing a positive value sets the ratelimit
interval in ms. Default is DEFAULT_RATELIMIT_INTERVAL
(5000 ms).
What: /sys/bus/pci/devices/<dev>/aer/nonfatal_ratelimit_burst
Date: May 2025
KernelVersion: 6.16.0
Contact: linux-pci@vger.kernel.org
Description: Ratelimit burst for non-fatal uncorrectable error logs.
Writing a value changes the number of errors (burst)
allowed per interval before ratelimiting. Reading gets the
current ratelimit burst. Default is DEFAULT_RATELIMIT_BURST
(10).

View file

@ -0,0 +1,10 @@
.. SPDX-License-Identifier: GPL-2.0
===========================================
PCI Native Host Bridge and Endpoint Drivers
===========================================
.. toctree::
:maxdepth: 2
rcar-pcie-firmware

View file

@ -0,0 +1,32 @@
.. SPDX-License-Identifier: GPL-2.0
=================================================
Firmware of PCIe controller for Renesas R-Car V4H
=================================================
Renesas R-Car V4H (r8a779g0) has a PCIe controller, requiring a specific
firmware download during startup.
However, Renesas currently cannot distribute the firmware free of charge.
The firmware file "104_PCIe_fw_addr_data_ver1.05.txt" (note that the file name
might be different between different datasheet revisions) can be found in the
datasheet encoded as text, and as such, the file's content must be converted
back to binary form. This can be achieved using the following example script:
.. code-block:: sh
$ awk '/^\s*0x[0-9A-Fa-f]{4}\s+0x[0-9A-Fa-f]{4}/ { print substr($2,5,2) substr($2,3,2) }' \
104_PCIe_fw_addr_data_ver1.05.txt | \
xxd -p -r > rcar_gen4_pcie.bin
Once the text content has been converted into a binary firmware file, verify
its checksum as follows:
.. code-block:: sh
$ sha1sum rcar_gen4_pcie.bin
1d0bd4b189b4eb009f5d564b1f93a79112994945 rcar_gen4_pcie.bin
The resulting binary file called "rcar_gen4_pcie.bin" should be placed in the
"/lib/firmware" directory before the driver runs.

View file

@ -8,6 +8,6 @@ PCI NVMe Function
The PCI NVMe endpoint function implements a PCI NVMe controller using the NVMe
subsystem target core code. The driver for this function resides with the NVMe
subsystem as drivers/nvme/target/nvmet-pciep.c.
subsystem as drivers/nvme/target/pci-epf.c.
See Documentation/nvme/nvme-pci-endpoint-target.rst for more details.

View file

@ -17,5 +17,6 @@ PCI Bus Subsystem
pci-error-recovery
pcieaer-howto
endpoint/index
controller/index
boot-interrupts
tph

View file

@ -85,12 +85,27 @@ In the example, 'Requester ID' means the ID of the device that sent
the error message to the Root Port. Please refer to PCIe specs for other
fields.
AER Ratelimits
--------------
Since error messages can be generated for each transaction, we may see
large volumes of errors reported. To prevent spammy devices from flooding
the console/stalling execution, messages are throttled by device and error
type (correctable vs. non-fatal uncorrectable). Fatal errors, including
DPC errors, are not ratelimited.
AER uses the default ratelimit of DEFAULT_RATELIMIT_BURST (10 events) over
DEFAULT_RATELIMIT_INTERVAL (5 seconds).
Ratelimits are exposed in the form of sysfs attributes and configurable.
See Documentation/ABI/testing/sysfs-bus-pci-devices-aer.
AER Statistics / Counters
-------------------------
When PCIe AER errors are captured, the counters / statistics are also exposed
in the form of sysfs attributes which are documented at
Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats
Documentation/ABI/testing/sysfs-bus-pci-devices-aer.
Developer Guide
===============

View file

@ -17,6 +17,10 @@ description: |
implements its root ports. But the ATU found on most DesignWare
PCIe host bridges is absent.
On systems derived from T602x, the PHY registers are in a region
separate from the port registers. In that case, there is one PHY
register range per port register range.
All root ports share a single ECAM space, but separate GPIOs are
used to take the PCI devices on those ports out of reset. Therefore
the standard "reset-gpios" and "max-link-speed" properties appear on
@ -30,16 +34,18 @@ description: |
properties:
compatible:
items:
- enum:
- apple,t8103-pcie
- apple,t8112-pcie
- apple,t6000-pcie
- const: apple,pcie
oneOf:
- items:
- enum:
- apple,t8103-pcie
- apple,t8112-pcie
- apple,t6000-pcie
- const: apple,pcie
- const: apple,t6020-pcie
reg:
minItems: 3
maxItems: 6
maxItems: 10
reg-names:
minItems: 3
@ -50,6 +56,10 @@ properties:
- const: port1
- const: port2
- const: port3
- const: phy0
- const: phy1
- const: phy2
- const: phy3
ranges:
minItems: 2
@ -98,6 +108,15 @@ allOf:
maxItems: 5
interrupts:
maxItems: 3
- if:
properties:
compatible:
contains:
const: apple,t6020-pcie
then:
properties:
reg-names:
minItems: 10
examples:
- |

View file

@ -186,49 +186,48 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
scb {
#address-cells = <2>;
#size-cells = <1>;
pcie0: pcie@7d500000 {
compatible = "brcm,bcm2711-pcie";
reg = <0x0 0x7d500000 0x9310>;
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "msi";
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH
0 0 0 2 &gicv2 GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH
0 0 0 3 &gicv2 GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH
0 0 0 4 &gicv2 GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <2>;
#size-cells = <1>;
pcie0: pcie@7d500000 {
compatible = "brcm,bcm2711-pcie";
reg = <0x0 0x7d500000 0x9310>;
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "msi";
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH
0 0 0 2 &gicv2 GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH
0 0 0 3 &gicv2 GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH
0 0 0 4 &gicv2 GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
msi-parent = <&pcie0>;
msi-controller;
ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
dma-ranges = <0x42000000 0x1 0x00000000 0x0 0x40000000 0x0 0x80000000>,
<0x42000000 0x1 0x80000000 0x3 0x00000000 0x0 0x80000000>;
brcm,enable-ssc;
brcm,scb-sizes = <0x0000000080000000 0x0000000080000000>;
msi-parent = <&pcie0>;
msi-controller;
ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
dma-ranges = <0x42000000 0x1 0x00000000 0x0 0x40000000 0x0 0x80000000>,
<0x42000000 0x1 0x80000000 0x3 0x00000000 0x0 0x80000000>;
brcm,enable-ssc;
brcm,scb-sizes = <0x0000000080000000 0x0000000080000000>;
/* PCIe bridge, Root Port */
pci@0,0 {
#address-cells = <3>;
#size-cells = <2>;
reg = <0x0 0x0 0x0 0x0 0x0>;
compatible = "pciclass,0604";
device_type = "pci";
vpcie3v3-supply = <&vreg7>;
ranges;
/* PCIe bridge, Root Port */
pci@0,0 {
#address-cells = <3>;
#size-cells = <2>;
reg = <0x0 0x0 0x0 0x0 0x0>;
compatible = "pciclass,0604";
device_type = "pci";
vpcie3v3-supply = <&vreg7>;
ranges;
/* PCIe endpoint */
pci-ep@0,0 {
assigned-addresses =
<0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>;
reg = <0x0 0x0 0x0 0x0 0x0>;
compatible = "pci14e4,1688";
};
};
/* PCIe endpoint */
pci-ep@0,0 {
assigned-addresses = <0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>;
reg = <0x0 0x0 0x0 0x0 0x0>;
compatible = "pci14e4,1688";
};
};
};
};

View file

@ -37,14 +37,14 @@ examples:
#size-cells = <2>;
pcie-ep@fc000000 {
compatible = "cdns,cdns-pcie-ep";
reg = <0x0 0xfc000000 0x0 0x01000000>,
<0x0 0x80000000 0x0 0x40000000>;
reg-names = "reg", "mem";
cdns,max-outbound-regions = <16>;
max-functions = /bits/ 8 <8>;
phys = <&pcie_phy0>;
phy-names = "pcie-phy";
compatible = "cdns,cdns-pcie-ep";
reg = <0x0 0xfc000000 0x0 0x01000000>,
<0x0 0x80000000 0x0 0x40000000>;
reg-names = "reg", "mem";
cdns,max-outbound-regions = <16>;
max-functions = /bits/ 8 <8>;
phys = <&pcie_phy0>;
phy-names = "pcie-phy";
};
};
...

View file

@ -53,17 +53,17 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
pcie-ep@37000000 {
compatible = "intel,keembay-pcie-ep";
reg = <0x37000000 0x00001000>,
<0x37100000 0x00001000>,
<0x37300000 0x00001000>,
<0x36000000 0x01000000>,
<0x37800000 0x00000200>;
reg-names = "dbi", "dbi2", "atu", "addr_space", "apb";
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 108 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "pcie_ev", "pcie_err", "pcie_mem_access";
num-lanes = <2>;
compatible = "intel,keembay-pcie-ep";
reg = <0x37000000 0x00001000>,
<0x37100000 0x00001000>,
<0x37300000 0x00001000>,
<0x36000000 0x01000000>,
<0x37800000 0x00000200>;
reg-names = "dbi", "dbi2", "atu", "addr_space", "apb";
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 108 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "pcie_ev", "pcie_err", "pcie_mem_access";
num-lanes = <2>;
};

View file

@ -75,23 +75,23 @@ examples:
#define KEEM_BAY_A53_PCIE
#define KEEM_BAY_A53_AUX_PCIE
pcie@37000000 {
compatible = "intel,keembay-pcie";
reg = <0x37000000 0x00001000>,
<0x37300000 0x00001000>,
<0x36e00000 0x00200000>,
<0x37800000 0x00000200>;
reg-names = "dbi", "atu", "config", "apb";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges = <0x02000000 0 0x36000000 0x36000000 0 0x00e00000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "pcie_ev", "pcie_err";
clocks = <&scmi_clk KEEM_BAY_A53_PCIE>,
<&scmi_clk KEEM_BAY_A53_AUX_PCIE>;
clock-names = "master", "aux";
reset-gpios = <&pca2 9 GPIO_ACTIVE_LOW>;
num-lanes = <2>;
compatible = "intel,keembay-pcie";
reg = <0x37000000 0x00001000>,
<0x37300000 0x00001000>,
<0x36e00000 0x00200000>,
<0x37800000 0x00000200>;
reg-names = "dbi", "atu", "config", "apb";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges = <0x02000000 0 0x36000000 0x36000000 0 0x00e00000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "pcie", "pcie_ev", "pcie_err";
clocks = <&scmi_clk KEEM_BAY_A53_PCIE>,
<&scmi_clk KEEM_BAY_A53_AUX_PCIE>;
clock-names = "master", "aux";
reset-gpios = <&pca2 9 GPIO_ACTIVE_LOW>;
num-lanes = <2>;
};

View file

@ -0,0 +1,100 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/pci/marvell,armada8k-pcie.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell Armada 7K/8K PCIe interface
maintainers:
- Thomas Petazzoni <thomas.petazzoni@bootlin.com>
description:
This PCIe host controller is based on the Synopsys DesignWare PCIe IP.
select:
properties:
compatible:
contains:
enum:
- marvell,armada8k-pcie
required:
- compatible
allOf:
- $ref: snps,dw-pcie.yaml#
properties:
compatible:
items:
- enum:
- marvell,armada8k-pcie
- const: snps,dw-pcie
reg:
maxItems: 2
reg-names:
items:
- const: ctrl
- const: config
clocks:
minItems: 1
maxItems: 2
clock-names:
items:
- const: core
- const: reg
interrupts:
maxItems: 1
msi-parent:
maxItems: 1
phys:
minItems: 1
maxItems: 4
phy-names:
minItems: 1
maxItems: 4
marvell,reset-gpio:
maxItems: 1
deprecated: true
required:
- interrupt-map
- clocks
- msi-parent
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
pcie@f2600000 {
compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
reg = <0xf2600000 0x10000>, <0xf6f00000 0x80000>;
reg-names = "ctrl", "config";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
dma-coherent;
msi-parent = <&gic_v2m0>;
ranges = <0x81000000 0 0xf9000000 0xf9000000 0 0x10000>, /* downstream I/O */
<0x82000000 0 0xf6000000 0xf6000000 0 0xf00000>; /* non-prefetchable memory */
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
clocks = <&cpm_syscon0 1 13>;
};
...

View file

@ -0,0 +1,277 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/pci/marvell,kirkwood-pcie.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell EBU PCIe interfaces
maintainers:
- Thomas Petazzoni <thomas.petazzoni@bootlin.com>
- Pali Rohár <pali@kernel.org>
allOf:
- $ref: /schemas/pci/pci-host-bridge.yaml#
properties:
compatible:
enum:
- marvell,armada-370-pcie
- marvell,armada-xp-pcie
- marvell,dove-pcie
- marvell,kirkwood-pcie
ranges:
description: >
The ranges describing the MMIO registers have the following layout:
0x82000000 0 r MBUS_ID(0xf0, 0x01) r 0 s
where:
* r is a 32-bits value that gives the offset of the MMIO registers of
this PCIe interface, from the base of the internal registers.
* s is a 32-bits value that give the size of this MMIO registers area.
This range entry translates the '0x82000000 0 r' PCI address into the
'MBUS_ID(0xf0, 0x01) r' CPU address, which is part of the internal
register window (as identified by MBUS_ID(0xf0, 0x01)).
The ranges describing the MBus windows have the following layout:
0x8t000000 s 0 MBUS_ID(w, a) 0 1 0
where:
* t is the type of the MBus window (as defined by the standard PCI DT
bindings), 1 for I/O and 2 for memory.
* s is the PCI slot that corresponds to this PCIe interface
* w is the 'target ID' value for the MBus window
* a the 'attribute' value for the MBus window.
Since the location and size of the different MBus windows is not fixed in
hardware, and only determined in runtime, those ranges cover the full first
4 GB of the physical address space, and do not translate into a valid CPU
address.
msi-parent:
maxItems: 1
patternProperties:
'^pcie@':
type: object
allOf:
- $ref: /schemas/pci/pci-bus-common.yaml#
- $ref: /schemas/pci/pci-device.yaml#
unevaluatedProperties: false
properties:
clocks:
maxItems: 1
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: intx
- const: error
reset-delay-us:
default: 100000
description: todo
marvell,pcie-port:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 3
description: todo
marvell,pcie-lane:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 3
description: todo
interrupt-controller:
type: object
additionalProperties: false
properties:
interrupt-controller: true
'#interrupt-cells':
const: 1
required:
- assigned-addresses
- clocks
- interrupt-map
- marvell,pcie-port
unevaluatedProperties: false
examples:
- |
#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
soc {
#address-cells = <2>;
#size-cells = <2>;
pcie@f001000000000000 {
compatible = "marvell,armada-xp-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
bus-range = <0x00 0xff>;
msi-parent = <&mpic>;
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000 /* Port 3.0 registers */
0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000 /* Port 1.1 registers */
0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000 /* Port 1.2 registers */
0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000 /* Port 1.3 registers */
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
0x81000000 0x2 0 MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO */
0x82000000 0x3 0 MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
0x82000000 0x6 0 MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
0x81000000 0x6 0 MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO */
0x82000000 0x7 0 MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
0x81000000 0x7 0 MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO */
0x82000000 0x8 0 MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
0x81000000 0x8 0 MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO */
0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */
0x82000000 0xa 0 MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
0x81000000 0xa 0 MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO */>;
pcie@1,0 {
device_type = "pci";
assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
reg = <0x0800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
0x81000000 0 0 0x81000000 0x1 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 58>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
/* low-active PERST# reset on GPIO 25 */
reset-gpios = <&gpio0 25 1>;
/* wait 20ms for device settle after reset deassertion */
reset-delay-us = <20000>;
clocks = <&gateclk 5>;
};
pcie@2,0 {
device_type = "pci";
assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
0x81000000 0 0 0x81000000 0x2 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 59>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
num-lanes = <1>;
clocks = <&gateclk 6>;
};
pcie@3,0 {
device_type = "pci";
assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
0x81000000 0 0 0x81000000 0x3 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 60>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <2>;
num-lanes = <1>;
clocks = <&gateclk 7>;
};
pcie@4,0 {
device_type = "pci";
assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
0x81000000 0 0 0x81000000 0x4 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 61>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <3>;
num-lanes = <1>;
clocks = <&gateclk 8>;
};
pcie@5,0 {
device_type = "pci";
assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
0x81000000 0 0 0x81000000 0x5 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 62>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
clocks = <&gateclk 9>;
};
pcie@6,0 {
device_type = "pci";
assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
reg = <0x3000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
0x81000000 0 0 0x81000000 0x6 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 63>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <1>;
num-lanes = <1>;
clocks = <&gateclk 10>;
};
};
};
...

View file

@ -50,7 +50,7 @@ properties:
items:
pattern: '^fic[0-3]$'
dma-coherent: true
dma-noncoherent: true
ranges:
minItems: 1
@ -65,33 +65,33 @@ unevaluatedProperties: false
examples:
- |
soc {
#address-cells = <2>;
#address-cells = <2>;
#size-cells = <2>;
pcie0: pcie@2030000000 {
compatible = "microchip,pcie-host-1.0";
reg = <0x0 0x70000000 0x0 0x08000000>,
<0x0 0x43008000 0x0 0x00002000>,
<0x0 0x4300a000 0x0 0x00002000>;
reg-names = "cfg", "bridge", "ctrl";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
pcie0: pcie@2030000000 {
compatible = "microchip,pcie-host-1.0";
reg = <0x0 0x70000000 0x0 0x08000000>,
<0x0 0x43008000 0x0 0x00002000>,
<0x0 0x4300a000 0x0 0x00002000>;
reg-names = "cfg", "bridge", "ctrl";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupts = <119>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
<0 0 0 2 &pcie_intc0 1>,
<0 0 0 3 &pcie_intc0 2>,
<0 0 0 4 &pcie_intc0 3>;
interrupt-parent = <&plic0>;
msi-parent = <&pcie0>;
msi-controller;
bus-range = <0x00 0x7f>;
ranges = <0x03000000 0x0 0x78000000 0x0 0x78000000 0x0 0x04000000>;
pcie_intc0: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
#interrupt-cells = <1>;
interrupts = <119>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
<0 0 0 2 &pcie_intc0 1>,
<0 0 0 3 &pcie_intc0 2>,
<0 0 0 4 &pcie_intc0 3>;
interrupt-parent = <&plic0>;
msi-parent = <&pcie0>;
msi-controller;
bus-range = <0x00 0x7f>;
ranges = <0x03000000 0x0 0x78000000 0x0 0x78000000 0x0 0x04000000>;
pcie_intc0: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
};

View file

@ -1,310 +0,0 @@
* Marvell EBU PCIe interfaces
Mandatory properties:
- compatible: one of the following values:
marvell,armada-370-pcie
marvell,armada-xp-pcie
marvell,dove-pcie
marvell,kirkwood-pcie
- #address-cells, set to <3>
- #size-cells, set to <2>
- #interrupt-cells, set to <1>
- bus-range: PCI bus numbers covered
- device_type, set to "pci"
- ranges: ranges describing the MMIO registers to control the PCIe
interfaces, and ranges describing the MBus windows needed to access
the memory and I/O regions of each PCIe interface.
- msi-parent: Link to the hardware entity that serves as the Message
Signaled Interrupt controller for this PCI controller.
The ranges describing the MMIO registers have the following layout:
0x82000000 0 r MBUS_ID(0xf0, 0x01) r 0 s
where:
* r is a 32-bits value that gives the offset of the MMIO
registers of this PCIe interface, from the base of the internal
registers.
* s is a 32-bits value that give the size of this MMIO
registers area. This range entry translates the '0x82000000 0 r' PCI
address into the 'MBUS_ID(0xf0, 0x01) r' CPU address, which is part
of the internal register window (as identified by MBUS_ID(0xf0,
0x01)).
The ranges describing the MBus windows have the following layout:
0x8t000000 s 0 MBUS_ID(w, a) 0 1 0
where:
* t is the type of the MBus window (as defined by the standard PCI DT
bindings), 1 for I/O and 2 for memory.
* s is the PCI slot that corresponds to this PCIe interface
* w is the 'target ID' value for the MBus window
* a the 'attribute' value for the MBus window.
Since the location and size of the different MBus windows is not fixed in
hardware, and only determined in runtime, those ranges cover the full first
4 GB of the physical address space, and do not translate into a valid CPU
address.
In addition, the device tree node must have sub-nodes describing each
PCIe interface, having the following mandatory properties:
- reg: used only for interrupt mapping, so only the first four bytes
are used to refer to the correct bus number and device number.
- assigned-addresses: reference to the MMIO registers used to control
this PCIe interface.
- clocks: the clock associated to this PCIe interface
- marvell,pcie-port: the physical PCIe port number
- status: either "disabled" or "okay"
- device_type, set to "pci"
- #address-cells, set to <3>
- #size-cells, set to <2>
- #interrupt-cells, set to <1>
- ranges, translating the MBus windows ranges of the parent node into
standard PCI addresses.
- interrupt-map-mask and interrupt-map, standard PCI properties to
define the mapping of the PCIe interface to interrupt numbers.
and the following optional properties:
- marvell,pcie-lane: the physical PCIe lane number, for ports having
multiple lanes. If this property is not found, we assume that the
value is 0.
- num-lanes: number of SerDes PCIe lanes for this link (1 or 4)
- reset-gpios: optional GPIO to PERST#
- reset-delay-us: delay in us to wait after reset de-assertion, if not
specified will default to 100ms, as required by the PCIe specification.
- interrupt-names: list of interrupt names, supported are:
- "intx" - interrupt line triggered by one of the legacy interrupt
- interrupts or interrupts-extended: List of the interrupt sources which
corresponding to the "interrupt-names". If non-empty then also additional
'interrupt-controller' subnode must be defined.
Example:
pcie-controller {
compatible = "marvell,armada-xp-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
bus-range = <0x00 0xff>;
msi-parent = <&mpic>;
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000 /* Port 3.0 registers */
0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000 /* Port 1.1 registers */
0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000 /* Port 1.2 registers */
0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000 /* Port 1.3 registers */
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
0x81000000 0x2 0 MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 0.1 IO */
0x82000000 0x3 0 MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 0.2 MEM */
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
0x82000000 0x6 0 MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
0x81000000 0x6 0 MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO */
0x82000000 0x7 0 MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
0x81000000 0x7 0 MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO */
0x82000000 0x8 0 MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
0x81000000 0x8 0 MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO */
0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */
0x82000000 0xa 0 MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
0x81000000 0xa 0 MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO */>;
pcie@1,0 {
device_type = "pci";
assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
reg = <0x0800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
0x81000000 0 0 0x81000000 0x1 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 58>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
/* low-active PERST# reset on GPIO 25 */
reset-gpios = <&gpio0 25 1>;
/* wait 20ms for device settle after reset deassertion */
reset-delay-us = <20000>;
clocks = <&gateclk 5>;
};
pcie@2,0 {
device_type = "pci";
assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
0x81000000 0 0 0x81000000 0x2 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 59>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <1>;
num-lanes = <1>;
clocks = <&gateclk 6>;
};
pcie@3,0 {
device_type = "pci";
assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
0x81000000 0 0 0x81000000 0x3 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 60>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <2>;
num-lanes = <1>;
clocks = <&gateclk 7>;
};
pcie@4,0 {
device_type = "pci";
assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
0x81000000 0 0 0x81000000 0x4 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 61>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <3>;
num-lanes = <1>;
clocks = <&gateclk 8>;
};
pcie@5,0 {
device_type = "pci";
assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
0x81000000 0 0 0x81000000 0x5 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 62>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
clocks = <&gateclk 9>;
};
pcie@6,0 {
device_type = "pci";
assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
reg = <0x3000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
0x81000000 0 0 0x81000000 0x6 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 63>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <1>;
num-lanes = <1>;
clocks = <&gateclk 10>;
};
pcie@7,0 {
device_type = "pci";
assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
reg = <0x3800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
0x81000000 0 0 0x81000000 0x7 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 64>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <2>;
num-lanes = <1>;
clocks = <&gateclk 11>;
};
pcie@8,0 {
device_type = "pci";
assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
reg = <0x4000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
0x81000000 0 0 0x81000000 0x8 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 65>;
marvell,pcie-port = <1>;
marvell,pcie-lane = <3>;
num-lanes = <1>;
clocks = <&gateclk 12>;
};
pcie@9,0 {
device_type = "pci";
assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
reg = <0x4800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
0x81000000 0 0 0x81000000 0x9 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 99>;
marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
clocks = <&gateclk 26>;
};
pcie@a,0 {
device_type = "pci";
assigned-addresses = <0x82005000 0 0x82000 0 0x2000>;
reg = <0x5000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
0x81000000 0 0 0x81000000 0xa 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 103>;
marvell,pcie-port = <3>;
marvell,pcie-lane = <0>;
num-lanes = <1>;
clocks = <&gateclk 27>;
};
};

View file

@ -74,7 +74,7 @@ properties:
reset-gpios:
description: Must contain a phandle to a GPIO controller followed by GPIO
that is being used as PERST input signal. Please refer to pci.txt.
that is being used as PERST input signal.
phys:
minItems: 1

View file

@ -1,48 +0,0 @@
* Marvell Armada 7K/8K PCIe interface
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in snps,dw-pcie.yaml.
Required properties:
- compatible: "marvell,armada8k-pcie"
- reg: must contain two register regions
- the control register region
- the config space region
- reg-names:
- "ctrl" for the control register region
- "config" for the config space region
- interrupts: Interrupt specifier for the PCIe controller
- clocks: reference to the PCIe controller clocks
- clock-names: mandatory if there is a second clock, in this case the
name must be "core" for the first clock and "reg" for the second
one
Optional properties:
- phys: phandle(s) to PHY node(s) following the generic PHY bindings.
Either 1, 2 or 4 PHYs might be needed depending on the number of
PCIe lanes.
- phy-names: names of the PHYs corresponding to the number of lanes.
Must be "cp0-pcie0-x4-lane0-phy", "cp0-pcie0-x4-lane1-phy" for
2 PHYs.
Example:
pcie@f2600000 {
compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
reg = <0 0xf2600000 0 0x10000>, <0 0xf6f00000 0 0x80000>;
reg-names = "ctrl", "config";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
dma-coherent;
bus-range = <0 0xff>;
ranges = <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000 /* downstream I/O */
0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>; /* non-prefetchable memory */
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
num-lanes = <1>;
clocks = <&cpm_syscon0 1 13>;
};

View file

@ -1,171 +0,0 @@
This document describes the generic device tree binding for describing the
relationship between PCI(e) devices and IOMMU(s).
Each PCI(e) device under a root complex is uniquely identified by its Requester
ID (AKA RID). A Requester ID is a triplet of a Bus number, Device number, and
Function number.
For the purpose of this document, when treated as a numeric value, a RID is
formatted such that:
* Bits [15:8] are the Bus number.
* Bits [7:3] are the Device number.
* Bits [2:0] are the Function number.
* Any other bits required for padding must be zero.
IOMMUs may distinguish PCI devices through sideband data derived from the
Requester ID. While a given PCI device can only master through one IOMMU, a
root complex may split masters across a set of IOMMUs (e.g. with one IOMMU per
bus).
The generic 'iommus' property is insufficient to describe this relationship,
and a mechanism is required to map from a PCI device to its IOMMU and sideband
data.
For generic IOMMU bindings, see
Documentation/devicetree/bindings/iommu/iommu.txt.
PCI root complex
================
Optional properties
-------------------
- iommu-map: Maps a Requester ID to an IOMMU and associated IOMMU specifier
data.
The property is an arbitrary number of tuples of
(rid-base,iommu,iommu-base,length).
Any RID r in the interval [rid-base, rid-base + length) is associated with
the listed IOMMU, with the IOMMU specifier (r - rid-base + iommu-base).
- iommu-map-mask: A mask to be applied to each Requester ID prior to being
mapped to an IOMMU specifier per the iommu-map property.
Example (1)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
iommu: iommu@a {
reg = <0xa 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the IOMMU is the RID,
* identity-mapped.
*/
iommu-map = <0x0 &iommu 0x0 0x10000>;
};
};
Example (2)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
iommu: iommu@a {
reg = <0xa 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the IOMMU is the RID with the
* function bits masked out.
*/
iommu-map = <0x0 &iommu 0x0 0x10000>;
iommu-map-mask = <0xfff8>;
};
};
Example (3)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
iommu: iommu@a {
reg = <0xa 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the IOMMU is the RID,
* but the high bits of the bus number are flipped.
*/
iommu-map = <0x0000 &iommu 0x8000 0x8000>,
<0x8000 &iommu 0x0000 0x8000>;
};
};
Example (4)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
iommu_a: iommu@a {
reg = <0xa 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
iommu_b: iommu@b {
reg = <0xb 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
iommu_c: iommu@c {
reg = <0xc 0x1>;
compatible = "vendor,some-iommu";
#iommu-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* Devices with bus number 0-127 are mastered via IOMMU
* a, with sideband data being RID[14:0].
* Devices with bus number 128-255 are mastered via
* IOMMU b, with sideband data being RID[14:0].
* No devices master via IOMMU c.
*/
iommu-map = <0x0000 &iommu_a 0x0000 0x8000>,
<0x8000 &iommu_b 0x0000 0x8000>;
};
};

View file

@ -1,220 +0,0 @@
This document describes the generic device tree binding for describing the
relationship between PCI devices and MSI controllers.
Each PCI device under a root complex is uniquely identified by its Requester ID
(AKA RID). A Requester ID is a triplet of a Bus number, Device number, and
Function number.
For the purpose of this document, when treated as a numeric value, a RID is
formatted such that:
* Bits [15:8] are the Bus number.
* Bits [7:3] are the Device number.
* Bits [2:0] are the Function number.
* Any other bits required for padding must be zero.
MSIs may be distinguished in part through the use of sideband data accompanying
writes. In the case of PCI devices, this sideband data may be derived from the
Requester ID. A mechanism is required to associate a device with both the MSI
controllers it can address, and the sideband data that will be associated with
its writes to those controllers.
For generic MSI bindings, see
Documentation/devicetree/bindings/interrupt-controller/msi.txt.
PCI root complex
================
Optional properties
-------------------
- msi-map: Maps a Requester ID to an MSI controller and associated
msi-specifier data. The property is an arbitrary number of tuples of
(rid-base,msi-controller,msi-base,length), where:
* rid-base is a single cell describing the first RID matched by the entry.
* msi-controller is a single phandle to an MSI controller
* msi-base is an msi-specifier describing the msi-specifier produced for the
first RID matched by the entry.
* length is a single cell describing how many consecutive RIDs are matched
following the rid-base.
Any RID r in the interval [rid-base, rid-base + length) is associated with
the listed msi-controller, with the msi-specifier (r - rid-base + msi-base).
- msi-map-mask: A mask to be applied to each Requester ID prior to being mapped
to an msi-specifier per the msi-map property.
- msi-parent: Describes the MSI parent of the root complex itself. Where
the root complex and MSI controller do not pass sideband data with MSI
writes, this property may be used to describe the MSI controller(s)
used by PCI devices under the root complex, if defined as such in the
binding for the root complex.
Example (1)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, identity-mapped.
*/
msi-map = <0x0 &msi_a 0x0 0x10000>,
};
};
Example (2)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, masked to only the device and function bits.
*/
msi-map = <0x0 &msi_a 0x0 0x100>,
msi-map-mask = <0xff>
};
};
Example (3)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, but the high bit of the bus number is
* ignored.
*/
msi-map = <0x0000 &msi 0x0000 0x8000>,
<0x8000 &msi 0x0000 0x8000>;
};
};
Example (4)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, but the high bit of the bus number is
* negated.
*/
msi-map = <0x0000 &msi 0x8000 0x8000>,
<0x8000 &msi 0x0000 0x8000>;
};
};
Example (5)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi_a: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
msi_b: msi-controller@b {
reg = <0xb 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
msi_c: msi-controller@c {
reg = <0xc 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to MSI controller a is the
* RID, but the high bit of the bus number is negated.
* The sideband data provided to MSI controller b is the
* RID, identity-mapped.
* MSI controller c is not addressable.
*/
msi-map = <0x0000 &msi_a 0x8000 0x08000>,
<0x8000 &msi_a 0x0000 0x08000>,
<0x0000 &msi_b 0x0000 0x10000>;
};
};

View file

@ -1,84 +0,0 @@
PCI bus bridges have standardized Device Tree bindings:
PCI Bus Binding to: IEEE Std 1275-1994
https://www.devicetree.org/open-firmware/bindings/pci/pci2_1.pdf
And for the interrupt mapping part:
Open Firmware Recommended Practice: Interrupt Mapping
https://www.devicetree.org/open-firmware/practice/imap/imap0_9d.pdf
Additionally to the properties specified in the above standards a host bridge
driver implementation may support the following properties:
- linux,pci-domain:
If present this property assigns a fixed PCI domain number to a host bridge,
otherwise an unstable (across boots) unique number will be assigned.
It is required to either not set this property at all or set it for all
host bridges in the system, otherwise potentially conflicting domain numbers
may be assigned to root buses behind different host bridges. The domain
number for each host bridge in the system must be unique.
- max-link-speed:
If present this property specifies PCI gen for link capability. Host
drivers could add this as a strategy to avoid unnecessary operation for
unsupported link speed, for instance, trying to do training for
unsupported link speed, etc. Must be '4' for gen4, '3' for gen3, '2'
for gen2, and '1' for gen1. Any other values are invalid.
- reset-gpios:
If present this property specifies PERST# GPIO. Host drivers can parse the
GPIO and apply fundamental reset to endpoints.
- supports-clkreq:
If present this property specifies that CLKREQ signal routing exists from
root port to downstream device and host bridge drivers can do programming
which depends on CLKREQ signal existence. For example, programming root port
not to advertise ASPM L1 Sub-States support if there is no CLKREQ signal.
PCI-PCI Bridge properties
-------------------------
PCIe root ports and switch ports may be described explicitly in the device
tree, as children of the host bridge node. Even though those devices are
discoverable by probing, it might be necessary to describe properties that
aren't provided by standard PCIe capabilities.
Required properties:
- reg:
Identifies the PCI-PCI bridge. As defined in the IEEE Std 1275-1994
document, it is a five-cell address encoded as (phys.hi phys.mid
phys.lo size.hi size.lo). phys.hi should contain the device's BDF as
0b00000000 bbbbbbbb dddddfff 00000000. The other cells should be zero.
The bus number is defined by firmware, through the standard bridge
configuration mechanism. If this port is a switch port, then firmware
allocates the bus number and writes it into the Secondary Bus Number
register of the bridge directly above this port. Otherwise, the bus
number of a root port is the first number in the bus-range property,
defaulting to zero.
If firmware leaves the ARI Forwarding Enable bit set in the bridge
above this port, then phys.hi contains the 8-bit function number as
0b00000000 bbbbbbbb ffffffff 00000000. Note that the PCIe specification
recommends that firmware only leaves ARI enabled when it knows that the
OS is ARI-aware.
Optional properties:
- external-facing:
When present, the port is external-facing. All bridges and endpoints
downstream of this port are external to the machine. The OS can, for
example, use this information to identify devices that cannot be
trusted with relaxed DMA protection, as users could easily attach
malicious devices to this port.
Example:
pcie@10000000 {
compatible = "pci-host-ecam-generic";
...
pcie@0008 {
/* Root port 00:01.0 is external-facing */
reg = <0x00000800 0 0 0 0>;
external-facing;
};
};

View file

@ -45,9 +45,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -57,6 +58,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -129,7 +131,8 @@ examples:
<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>;
<GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0",
"msi1",
"msi2",
@ -137,7 +140,8 @@ examples:
"msi4",
"msi5",
"msi6",
"msi7";
"msi7",
"global";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,

View file

@ -54,9 +54,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -66,6 +67,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -149,9 +151,10 @@ examples:
<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>;
<GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7";
"msi4", "msi5", "msi6", "msi7", "global";
#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>,

View file

@ -49,9 +49,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -61,6 +62,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -136,7 +138,8 @@ examples:
<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>;
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0",
"msi1",
"msi2",
@ -144,7 +147,8 @@ examples:
"msi4",
"msi5",
"msi6",
"msi7";
"msi7",
"global";
#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 */

View file

@ -49,9 +49,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -61,6 +62,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -128,9 +130,10 @@ examples:
<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>;
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7";
"msi4", "msi5", "msi6", "msi7", "global";
#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 */

View file

@ -61,9 +61,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -73,6 +74,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -143,9 +145,10 @@ examples:
<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>;
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7";
"msi4", "msi5", "msi6", "msi7", "global";
#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 */

View file

@ -51,9 +51,10 @@ properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -63,6 +64,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
- const: global
resets:
maxItems: 1
@ -132,9 +134,10 @@ examples:
<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>;
<GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7";
"msi4", "msi5", "msi6", "msi7", "global";
#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 */

View file

@ -21,6 +21,7 @@ properties:
- qcom,pcie-apq8064
- qcom,pcie-apq8084
- qcom,pcie-ipq4019
- qcom,pcie-ipq5018
- qcom,pcie-ipq6018
- qcom,pcie-ipq8064
- qcom,pcie-ipq8064-v2
@ -168,6 +169,7 @@ allOf:
compatible:
contains:
enum:
- qcom,pcie-ipq5018
- qcom,pcie-ipq6018
- qcom,pcie-ipq8074-gen3
- qcom,pcie-ipq9574
@ -175,14 +177,16 @@ allOf:
properties:
reg:
minItems: 5
maxItems: 5
maxItems: 6
reg-names:
minItems: 5
items:
- const: dbi # DesignWare PCIe registers
- const: elbi # External local bus interface registers
- const: atu # ATU address space
- const: parf # Qualcomm specific registers
- const: config # PCIe configuration space
- const: mhi # MHI registers
- if:
properties:
@ -322,6 +326,53 @@ allOf:
- const: ahb # AHB reset
- const: phy_ahb # PHY AHB reset
- if:
properties:
compatible:
contains:
enum:
- qcom,pcie-ipq5018
then:
properties:
clocks:
minItems: 6
maxItems: 6
clock-names:
items:
- const: iface # PCIe to SysNOC BIU clock
- const: axi_m # AXI Master clock
- const: axi_s # AXI Slave clock
- const: ahb # AHB clock
- const: aux # Auxiliary clock
- const: axi_bridge # AXI bridge clock
resets:
minItems: 8
maxItems: 8
reset-names:
items:
- const: pipe # PIPE reset
- const: sleep # Sleep reset
- const: sticky # Core sticky reset
- const: axi_m # AXI master reset
- const: axi_s # AXI slave reset
- const: ahb # AHB reset
- const: axi_m_sticky # AXI master sticky reset
- const: axi_s_sticky # AXI slave sticky reset
interrupts:
minItems: 9
maxItems: 9
interrupt-names:
items:
- const: msi0
- const: msi1
- const: msi2
- const: msi3
- const: msi4
- const: msi5
- const: msi6
- const: msi7
- const: global
- if:
properties:
compatible:
@ -562,6 +613,7 @@ allOf:
enum:
- qcom,pcie-apq8064
- qcom,pcie-ipq4019
- qcom,pcie-ipq5018
- qcom,pcie-ipq8064
- qcom,pcie-ipq8064v2
- qcom,pcie-ipq8074
@ -589,7 +641,11 @@ allOf:
compatible:
contains:
enum:
- qcom,pcie-ipq6018
- qcom,pcie-ipq8074
- qcom,pcie-ipq8074-gen3
- qcom,pcie-msm8996
- qcom,pcie-msm8998
- qcom,pcie-sdm845
then:
oneOf:
@ -602,8 +658,9 @@ allOf:
- properties:
interrupts:
minItems: 8
maxItems: 8
maxItems: 9
interrupt-names:
minItems: 8
items:
- const: msi0
- const: msi1
@ -613,6 +670,7 @@ allOf:
- const: msi5
- const: msi6
- const: msi7
- const: global
- if:
properties:
@ -622,11 +680,8 @@ allOf:
- qcom,pcie-apq8064
- qcom,pcie-apq8084
- qcom,pcie-ipq4019
- qcom,pcie-ipq6018
- qcom,pcie-ipq8064
- qcom,pcie-ipq8064-v2
- qcom,pcie-ipq8074
- qcom,pcie-ipq8074-gen3
- qcom,pcie-qcs404
then:
properties:

View file

@ -73,21 +73,21 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a774c0-sysc.h>
pcie0_ep: pcie-ep@fe000000 {
compatible = "renesas,r8a774c0-pcie-ep",
"renesas,rcar-gen3-pcie-ep";
reg = <0xfe000000 0x80000>,
<0xfe100000 0x100000>,
<0xfe200000 0x200000>,
<0x30000000 0x8000000>,
<0x38000000 0x8000000>;
reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
resets = <&cpg 319>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
clocks = <&cpg CPG_MOD 319>;
clock-names = "pcie";
max-functions = /bits/ 8 <1>;
pcie0_ep: pcie-ep@fe000000 {
compatible = "renesas,r8a774c0-pcie-ep",
"renesas,rcar-gen3-pcie-ep";
reg = <0xfe000000 0x80000>,
<0xfe100000 0x100000>,
<0xfe200000 0x200000>,
<0x30000000 0x8000000>,
<0x38000000 0x8000000>;
reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
resets = <&cpg 319>;
power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
clocks = <&cpg CPG_MOD 319>;
clock-names = "pcie";
max-functions = /bits/ 8 <1>;
};

View file

@ -113,27 +113,27 @@ examples:
pcie: pcie@fe000000 {
compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2";
reg = <0 0xfe000000 0 0x80000>;
#address-cells = <3>;
#size-cells = <2>;
bus-range = <0x00 0xff>;
device_type = "pci";
ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000>,
<0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>,
<0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>,
<0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>,
<0x42000000 2 0x00000000 2 0x00000000 0 0x40000000>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
clock-names = "pcie", "pcie_bus";
power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
resets = <&cpg 319>;
vpcie3v3-supply = <&pcie_3v3>;
vpcie12v-supply = <&pcie_12v>;
};
#address-cells = <3>;
#size-cells = <2>;
bus-range = <0x00 0xff>;
device_type = "pci";
ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000>,
<0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>,
<0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>,
<0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>,
<0x42000000 2 0x00000000 2 0x00000000 0 0x40000000>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
clock-names = "pcie", "pcie_bus";
power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
resets = <&cpg 319>;
vpcie3v3-supply = <&pcie_3v3>;
vpcie12v-supply = <&pcie_12v>;
};
};

View file

@ -65,7 +65,11 @@ properties:
tx_cpl_timeout, cor_err_sent, nf_err_sent, f_err_sent, cor_err_rx,
nf_err_rx, f_err_rx, radm_qoverflow
- description:
eDMA write channel 0 interrupt
If the matching interrupt name is "msi", then this is the combined
MSI line interrupt, which is to support MSI interrupts output to GIC
controller via GIC SPI interrupt instead of GIC ITS interrupt.
If the matching interrupt name is "dma0", then this is the eDMA write
channel 0 interrupt.
- description:
eDMA write channel 1 interrupt
- description:
@ -81,7 +85,9 @@ properties:
- const: msg
- const: legacy
- const: err
- const: dma0
- enum:
- msi
- dma0
- const: dma1
- const: dma2
- const: dma3

View file

@ -16,16 +16,14 @@ description: |+
PCIe IP and thus inherits all the common properties defined in
snps,dw-pcie.yaml.
allOf:
- $ref: /schemas/pci/snps,dw-pcie.yaml#
- $ref: /schemas/pci/rockchip-dw-pcie-common.yaml#
properties:
compatible:
oneOf:
- const: rockchip,rk3568-pcie
- items:
- enum:
- rockchip,rk3562-pcie
- rockchip,rk3576-pcie
- rockchip,rk3588-pcie
- const: rockchip,rk3568-pcie
@ -71,8 +69,58 @@ properties:
vpcie3v3-supply: true
required:
- msi-map
allOf:
- $ref: /schemas/pci/snps,dw-pcie.yaml#
- $ref: /schemas/pci/rockchip-dw-pcie-common.yaml#
- if:
not:
properties:
compatible:
contains:
enum:
- rockchip,rk3562-pcie
- rockchip,rk3576-pcie
then:
required:
- msi-map
- if:
properties:
compatible:
contains:
enum:
- rockchip,rk3562-pcie
- rockchip,rk3576-pcie
then:
properties:
interrupts:
minItems: 6
maxItems: 6
interrupt-names:
items:
- const: sys
- const: pmc
- const: msg
- const: legacy
- const: err
- const: msi
else:
properties:
interrupts:
minItems: 5
interrupt-names:
minItems: 5
items:
- const: sys
- const: pmc
- const: msg
- const: legacy
- const: err
- const: dma0
- const: dma1
- const: dma2
- const: dma3
unevaluatedProperties: false

View file

@ -81,10 +81,10 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/sifive-fu740-prci.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
#include <dt-bindings/clock/sifive-fu740-prci.h>
pcie@e00000000 {
compatible = "sifive,fu740-pcie";

View file

@ -115,7 +115,7 @@ properties:
above for new bindings.
oneOf:
- description: See native 'dbi' clock for details
enum: [ pcie, pcie_apb_sys, aclk_dbi ]
enum: [ pcie, pcie_apb_sys, aclk_dbi, reg ]
- description: See native 'mstr/slv' clock for details
enum: [ pcie_bus, pcie_inbound_axi, pcie_aclk, aclk_mst, aclk_slv ]
- description: See native 'pipe' clock for details
@ -201,6 +201,7 @@ properties:
oneOf:
- pattern: '^pcie(-?phy[0-9]*)?$'
- pattern: '^p2u-[0-7]$'
- pattern: '^cp[01]-pcie[0-2]-x[124](-lane[0-3])?-phy$' # marvell,armada8k-pcie
reset-gpio:
deprecated: true

View file

@ -105,6 +105,8 @@ properties:
Vendor-specific CSR names. Consider using the generic names above
for new bindings.
oneOf:
- description: See native 'dbi' CSR region for details.
enum: [ ctrl ]
- description: See native 'elbi/app' CSR region for details.
enum: [ apb, mgmt, link, ulreg, appl ]
- description: See native 'atu' CSR region for details.
@ -117,7 +119,7 @@ properties:
const: slcr
allOf:
- contains:
const: dbi
enum: [ dbi, ctrl ]
- contains:
const: config

View file

@ -0,0 +1,100 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/pci/v3,v360epc-pci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: V3 Semiconductor V360 EPC PCI bridge
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description:
This bridge is found in the ARM Integrator/AP (Application Platform)
allOf:
- $ref: /schemas/pci/pci-host-bridge.yaml#
properties:
compatible:
items:
- const: arm,integrator-ap-pci
- const: v3,v360epc-pci
reg:
items:
- description: V3 host bridge controller
- description: Configuration space
clocks:
maxItems: 1
dma-ranges:
maxItems: 2
description:
The inbound ranges must be aligned to a 1MB boundary, and may be 1MB, 2MB,
4MB, 8MB, 16MB, 32MB, 64MB, 128MB, 256MB, 512MB, 1GB or 2GB in size. The
memory should be marked as pre-fetchable.
interrupts:
description: Bus Error IRQ
maxItems: 1
ranges:
description:
The non-prefetchable and prefetchable memory windows must each be exactly
256MB (0x10000000) in size. The prefetchable memory window must be
immediately adjacent to the non-prefetchable memory window.
required:
- compatible
- reg
- clocks
- dma-ranges
- "#interrupt-cells"
- interrupt-map
- interrupt-map-mask
unevaluatedProperties: false
examples:
- |
pci@62000000 {
compatible = "arm,integrator-ap-pci", "v3,v360epc-pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x62000000 0x10000>, <0x61000000 0x01000000>;
device_type = "pci";
interrupt-parent = <&pic>;
interrupts = <17>; /* Bus error IRQ */
clocks = <&pciclk>;
ranges = <0x01000000 0 0x00000000 0x60000000 0 0x01000000>, /* 16 MiB @ LB 60000000 */
<0x02000000 0 0x40000000 0x40000000 0 0x10000000>, /* 256 MiB @ LB 40000000 1:1 */
<0x42000000 0 0x50000000 0x50000000 0 0x10000000>; /* 256 MiB @ LB 50000000 1:1 */
dma-ranges = <0x02000000 0 0x20000000 0x20000000 0 0x20000000>, /* EBI: 512 MB @ LB 20000000 1:1 */
<0x02000000 0 0x80000000 0x80000000 0 0x40000000>; /* CM alias: 1GB @ LB 80000000 */
interrupt-map-mask = <0xf800 0 0 0x7>;
interrupt-map =
/* IDSEL 9 */
<0x4800 0 0 1 &pic 13>, /* INT A on slot 9 is irq 13 */
<0x4800 0 0 2 &pic 14>, /* INT B on slot 9 is irq 14 */
<0x4800 0 0 3 &pic 15>, /* INT C on slot 9 is irq 15 */
<0x4800 0 0 4 &pic 16>, /* INT D on slot 9 is irq 16 */
/* IDSEL 10 */
<0x5000 0 0 1 &pic 14>, /* INT A on slot 10 is irq 14 */
<0x5000 0 0 2 &pic 15>, /* INT B on slot 10 is irq 15 */
<0x5000 0 0 3 &pic 16>, /* INT C on slot 10 is irq 16 */
<0x5000 0 0 4 &pic 13>, /* INT D on slot 10 is irq 13 */
/* IDSEL 11 */
<0x5800 0 0 1 &pic 15>, /* INT A on slot 11 is irq 15 */
<0x5800 0 0 2 &pic 16>, /* INT B on slot 11 is irq 16 */
<0x5800 0 0 3 &pic 13>, /* INT C on slot 11 is irq 13 */
<0x5800 0 0 4 &pic 14>, /* INT D on slot 11 is irq 14 */
/* IDSEL 12 */
<0x6000 0 0 1 &pic 16>, /* INT A on slot 12 is irq 16 */
<0x6000 0 0 2 &pic 13>, /* INT B on slot 12 is irq 13 */
<0x6000 0 0 3 &pic 14>, /* INT C on slot 12 is irq 14 */
<0x6000 0 0 4 &pic 15>; /* INT D on slot 12 is irq 15 */
};
...

View file

@ -1,76 +0,0 @@
V3 Semiconductor V360 EPC PCI bridge
This bridge is found in the ARM Integrator/AP (Application Platform)
Required properties:
- compatible: should be one of:
"v3,v360epc-pci"
"arm,integrator-ap-pci", "v3,v360epc-pci"
- reg: should contain two register areas:
first the base address of the V3 host bridge controller, 64KB
second the configuration area register space, 16MB
- interrupts: should contain a reference to the V3 error interrupt
as routed on the system.
- bus-range: see pci.txt
- ranges: this follows the standard PCI bindings in the IEEE Std
1275-1994 (see pci.txt) with the following restriction:
- The non-prefetchable and prefetchable memory windows must
each be exactly 256MB (0x10000000) in size.
- The prefetchable memory window must be immediately adjacent
to the non-prefetcable memory window
- dma-ranges: three ranges for the inbound memory region. The ranges must
be aligned to a 1MB boundary, and may be 1MB, 2MB, 4MB, 8MB, 16MB, 32MB,
64MB, 128MB, 256MB, 512MB, 1GB or 2GB in size. The memory should be marked
as pre-fetchable. Two ranges are supported by the hardware.
Integrator-specific required properties:
- syscon: should contain a link to the syscon device node, since
on the Integrator, some registers in the syscon are required to
operate the V3 host bridge.
Example:
pci: pciv3@62000000 {
compatible = "arm,integrator-ap-pci", "v3,v360epc-pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x62000000 0x10000>, <0x61000000 0x01000000>;
interrupt-parent = <&pic>;
interrupts = <17>; /* Bus error IRQ */
clocks = <&pciclk>;
bus-range = <0x00 0xff>;
ranges = 0x01000000 0 0x00000000 /* I/O space @00000000 */
0x60000000 0 0x01000000 /* 16 MiB @ LB 60000000 */
0x02000000 0 0x40000000 /* non-prefectable memory @40000000 */
0x40000000 0 0x10000000 /* 256 MiB @ LB 40000000 1:1 */
0x42000000 0 0x50000000 /* prefetchable memory @50000000 */
0x50000000 0 0x10000000>; /* 256 MiB @ LB 50000000 1:1 */
dma-ranges = <0x02000000 0 0x20000000 /* EBI memory space */
0x20000000 0 0x20000000 /* 512 MB @ LB 20000000 1:1 */
0x02000000 0 0x80000000 /* Core module alias memory */
0x80000000 0 0x40000000>; /* 1GB @ LB 80000000 */
interrupt-map-mask = <0xf800 0 0 0x7>;
interrupt-map = <
/* IDSEL 9 */
0x4800 0 0 1 &pic 13 /* INT A on slot 9 is irq 13 */
0x4800 0 0 2 &pic 14 /* INT B on slot 9 is irq 14 */
0x4800 0 0 3 &pic 15 /* INT C on slot 9 is irq 15 */
0x4800 0 0 4 &pic 16 /* INT D on slot 9 is irq 16 */
/* IDSEL 10 */
0x5000 0 0 1 &pic 14 /* INT A on slot 10 is irq 14 */
0x5000 0 0 2 &pic 15 /* INT B on slot 10 is irq 15 */
0x5000 0 0 3 &pic 16 /* INT C on slot 10 is irq 16 */
0x5000 0 0 4 &pic 13 /* INT D on slot 10 is irq 13 */
/* IDSEL 11 */
0x5800 0 0 1 &pic 15 /* INT A on slot 11 is irq 15 */
0x5800 0 0 2 &pic 16 /* INT B on slot 11 is irq 16 */
0x5800 0 0 3 &pic 13 /* INT C on slot 11 is irq 13 */
0x5800 0 0 4 &pic 14 /* INT D on slot 11 is irq 14 */
/* IDSEL 12 */
0x6000 0 0 1 &pic 16 /* INT A on slot 12 is irq 16 */
0x6000 0 0 2 &pic 13 /* INT B on slot 12 is irq 13 */
0x6000 0 0 3 &pic 14 /* INT C on slot 12 is irq 14 */
0x6000 0 0 4 &pic 15 /* INT D on slot 12 is irq 15 */
>;
};

View file

@ -76,64 +76,62 @@ unevaluatedProperties: false
examples:
- |
versal {
#address-cells = <2>;
#size-cells = <2>;
cpm_pcie: pcie@fca10000 {
compatible = "xlnx,versal-cpm-host-1.00";
device_type = "pci";
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
interrupts = <0 72 4>;
interrupt-parent = <&gic>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc_0 0>,
<0 0 0 2 &pcie_intc_0 1>,
<0 0 0 3 &pcie_intc_0 2>,
<0 0 0 4 &pcie_intc_0 3>;
bus-range = <0x00 0xff>;
ranges = <0x02000000 0x0 0xe0010000 0x0 0xe0010000 0x0 0x10000000>,
<0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
msi-map = <0x0 &its_gic 0x0 0x10000>;
reg = <0x0 0xfca10000 0x0 0x1000>,
<0x6 0x00000000 0x0 0x10000000>;
reg-names = "cpm_slcr", "cfg";
pcie_intc_0: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
#address-cells = <2>;
#size-cells = <2>;
pcie@fca10000 {
compatible = "xlnx,versal-cpm-host-1.00";
device_type = "pci";
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
interrupts = <0 72 4>;
interrupt-parent = <&gic>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc_0 0>,
<0 0 0 2 &pcie_intc_0 1>,
<0 0 0 3 &pcie_intc_0 2>,
<0 0 0 4 &pcie_intc_0 3>;
bus-range = <0x00 0xff>;
ranges = <0x02000000 0x0 0xe0010000 0x0 0xe0010000 0x0 0x10000000>,
<0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
msi-map = <0x0 &its_gic 0x0 0x10000>;
reg = <0x0 0xfca10000 0x0 0x1000>,
<0x6 0x00000000 0x0 0x10000000>;
reg-names = "cpm_slcr", "cfg";
pcie_intc_0: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
cpm5_pcie: pcie@fcdd0000 {
compatible = "xlnx,versal-cpm5-host";
device_type = "pci";
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
interrupts = <0 72 4>;
interrupt-parent = <&gic>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
<0 0 0 2 &pcie_intc_1 1>,
<0 0 0 3 &pcie_intc_1 2>,
<0 0 0 4 &pcie_intc_1 3>;
bus-range = <0x00 0xff>;
ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
<0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
msi-map = <0x0 &its_gic 0x0 0x10000>;
reg = <0x00 0xfcdd0000 0x00 0x1000>,
<0x06 0x00000000 0x00 0x1000000>,
<0x00 0xfce20000 0x00 0x1000000>;
reg-names = "cpm_slcr", "cfg", "cpm_csr";
pcie_intc_1: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
pcie@fcdd0000 {
compatible = "xlnx,versal-cpm5-host";
device_type = "pci";
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
interrupts = <0 72 4>;
interrupt-parent = <&gic>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
<0 0 0 2 &pcie_intc_1 1>,
<0 0 0 3 &pcie_intc_1 2>,
<0 0 0 4 &pcie_intc_1 3>;
bus-range = <0x00 0xff>;
ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
<0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>;
msi-map = <0x0 &its_gic 0x0 0x10000>;
reg = <0x00 0xfcdd0000 0x00 0x1000>,
<0x06 0x00000000 0x00 0x1000000>,
<0x00 0xfce20000 0x00 0x1000000>;
reg-names = "cpm_slcr", "cfg", "cpm_csr";
pcie_intc_1: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
};

View file

@ -391,12 +391,11 @@ PCI
devm_pci_remap_cfgspace() : ioremap PCI configuration space
devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource
pcim_enable_device() : after success, some PCI ops become managed
pcim_enable_device() : after success, the PCI device gets disabled automatically on driver detach
pcim_iomap() : do iomap() on a single BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iounmap() : do iounmap() on a single BAR
pcim_iounmap_regions() : do iounmap() and release_region() on multiple BARs
pcim_pin_device() : keep PCI device enabled after release
pcim_set_mwi() : enable Memory-Write-Invalidate PCI transaction

View file

@ -2147,7 +2147,7 @@ F: arch/arm/plat-*/
ARM/ACTIONS SEMI ARCHITECTURE
M: Andreas Färber <afaerber@suse.de>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-actions@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -2400,7 +2400,7 @@ F: arch/arm/boot/dts/intel/axm/
F: arch/arm/mach-axxia/
ARM/BITMAIN ARCHITECTURE
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/bitmain.yaml
@ -3069,7 +3069,7 @@ F: include/linux/soc/qcom/
F: include/soc/qcom/
ARM/RDA MICRO ARCHITECTURE
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-unisoc@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -3776,7 +3776,7 @@ F: Documentation/admin-guide/aoe/
F: drivers/block/aoe/
ATC260X PMIC MFD DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
M: Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
L: linux-actions@lists.infradead.org
S: Maintained
@ -6806,7 +6806,7 @@ S: Orphan
F: drivers/mtd/nand/raw/denali*
DESIGNWARE EDMA CORE IP DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: dmaengine@vger.kernel.org
S: Maintained
F: drivers/dma/dw-edma/
@ -8652,7 +8652,7 @@ S: Maintained
F: drivers/edac/pnd2_edac.[ch]
EDAC-QCOM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-msm@vger.kernel.org
L: linux-edac@vger.kernel.org
S: Maintained
@ -12270,7 +12270,7 @@ M: Andy Shevchenko <andy@kernel.org>
L: linux-kernel@vger.kernel.org
S: Supported
F: arch/x86/include/asm/intel-mid.h
F: arch/x86/pci/intel_mid_pci.c
F: arch/x86/pci/intel_mid.c
F: arch/x86/platform/intel-mid/
F: drivers/dma/hsu/
F: drivers/extcon/extcon-intel-mrfld.c
@ -14859,7 +14859,7 @@ F: drivers/hid/hid-mcp2221.c
MCP251XFD SPI-CAN NETWORK DRIVER
M: Marc Kleine-Budde <mkl@pengutronix.de>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
R: Thomas Kopp <thomas.kopp@microchip.com>
L: linux-can@vger.kernel.org
S: Maintained
@ -16025,7 +16025,7 @@ F: arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts
F: arch/arm64/boot/dts/marvell/armada-3720-uDPU.*
MHI BUS
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: mhi@lists.linux.dev
L: linux-arm-msm@vger.kernel.org
S: Maintained
@ -18837,7 +18837,7 @@ M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
F: Documentation/devicetree/bindings/pci/marvell,armada8k-pcie.yaml
F: drivers/pci/controller/dwc/pcie-armada8k.c
PCI DRIVER FOR CADENCE PCIE IP
@ -18957,6 +18957,7 @@ M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
L: linux-pci@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Maintained
F: Documentation/PCI/controller/rcar-pcie-firmware.rst
F: Documentation/devicetree/bindings/pci/*rcar*
F: drivers/pci/controller/*rcar*
F: drivers/pci/controller/dwc/*rcar*
@ -18971,7 +18972,7 @@ F: drivers/pci/controller/dwc/pci-exynos.c
PCI DRIVER FOR SYNOPSYS DESIGNWARE
M: Jingoo Han <jingoohan1@gmail.com>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
@ -18994,7 +18995,7 @@ PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt
F: Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
F: drivers/pci/controller/pci-v3-semi.c
PCI DRIVER FOR XILINX VERSAL CPM
@ -19006,8 +19007,8 @@ F: Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml
F: drivers/pci/controller/pcie-xilinx-cpm.c
PCI ENDPOINT SUBSYSTEM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Krzysztof Wilczyński <kw@linux.com>
M: Manivannan Sadhasivam <mani@kernel.org>
M: Krzysztof Wilczyński <kwilczynski@kernel.org>
R: Kishon Vijay Abraham I <kishon@kernel.org>
L: linux-pci@vger.kernel.org
S: Supported
@ -19058,8 +19059,8 @@ F: drivers/pci/controller/pci-xgene-msi.c
PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
M: Krzysztof Wilczyński <kw@linux.com>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Krzysztof Wilczyński <kwilczynski@kernel.org>
M: Manivannan Sadhasivam <mani@kernel.org>
R: Rob Herring <robh@kernel.org>
L: linux-pci@vger.kernel.org
S: Supported
@ -19067,6 +19068,7 @@ Q: https://patchwork.kernel.org/project/linux-pci/list/
B: https://bugzilla.kernel.org
C: irc://irc.oftc.net/linux-pci
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
F: Documentation/ABI/testing/debugfs-pcie-ptm
F: Documentation/devicetree/bindings/pci/
F: drivers/pci/controller/
F: drivers/pci/pci-bridge-emul.c
@ -19215,7 +19217,7 @@ F: Documentation/devicetree/bindings/pci/microchip*
F: drivers/pci/controller/plda/*microchip*
PCIE DRIVER FOR QUALCOMM MSM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-pci@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
@ -19251,7 +19253,7 @@ F: Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
F: drivers/pci/controller/plda/pcie-starfive.c
PCIE ENDPOINT DRIVER FOR QUALCOMM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-pci@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
@ -20379,7 +20381,7 @@ F: drivers/iommu/arm/arm-smmu/arm-smmu-qcom*
F: drivers/iommu/msm_iommu*
QUALCOMM IPC ROUTER (QRTR) DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: include/trace/events/qrtr.h
@ -20387,7 +20389,7 @@ F: include/uapi/linux/qrtr.h
F: net/qrtr/
QUALCOMM IPCC MAILBOX DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
@ -20422,7 +20424,7 @@ F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml
F: drivers/media/platform/qcom/iris/
QUALCOMM NAND CONTROLLER DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-mtd@lists.infradead.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
@ -22990,7 +22992,7 @@ F: Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml
F: drivers/media/i2c/imx283.c
SONY IMX290 SENSOR DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -22999,7 +23001,7 @@ F: drivers/media/i2c/imx290.c
SONY IMX296 SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -25374,7 +25376,7 @@ S: Maintained
F: drivers/ufs/host/ufs-mediatek*
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER QUALCOMM HOOKS
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-msm@vger.kernel.org
L: linux-scsi@vger.kernel.org
S: Maintained

View file

@ -269,7 +269,7 @@ config ARCH_QCOM
bool "Qualcomm Platforms"
select GPIOLIB
select PINCTRL
select HAVE_PWRCTL if PCI
select HAVE_PWRCTRL if PCI
help
This enables support for the ARMv8 based Qualcomm chipsets.

View file

@ -8,13 +8,13 @@ obj-$(CONFIG_PCI_OLPC) += olpc.o
obj-$(CONFIG_PCI_XEN) += xen.o
obj-y += fixup.o
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
obj-$(CONFIG_ACPI) += acpi.o
obj-y += legacy.o irq.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
obj-$(CONFIG_X86_INTEL_MID) += intel_mid.o
obj-$(CONFIG_X86_INTEL_MID) += intel_mid_pci.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-y += common.o early.o
obj-y += bus_numa.o

View file

@ -8,7 +8,6 @@ config DRM_ACCEL_QAIC
depends on DRM_ACCEL
depends on PCI && HAS_IOMEM
depends on MHI_BUS
depends on MMU
select CRC32
help
Enables driver for Qualcomm's Cloud AI accelerator PCIe cards that are

View file

@ -3717,7 +3717,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rv) {
dev_warn(&pdev->dev, "64-bit DMA enable failed\n");
goto setmask_err;
goto iomap_err;
}
/* Copy the info we may need later into the private data structure. */
@ -3733,7 +3733,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
if (!dd->isr_workq) {
dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance);
rv = -ENOMEM;
goto setmask_err;
goto iomap_err;
}
memset(cpu_list, 0, sizeof(cpu_list));
@ -3830,8 +3830,6 @@ static int mtip_pci_probe(struct pci_dev *pdev,
drop_cpu(dd->work[1].cpu_binding);
drop_cpu(dd->work[2].cpu_binding);
}
setmask_err:
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
iomap_err:
kfree(dd);
@ -3907,7 +3905,6 @@ static void mtip_pci_remove(struct pci_dev *pdev)
pci_disable_msi(pdev);
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
pci_set_drvdata(pdev, NULL);
put_disk(dd->disk);

View file

@ -83,7 +83,7 @@ config FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST
config FIREWIRE_OHCI
tristate "OHCI-1394 controllers"
depends on PCI && FIREWIRE && MMU
depends on PCI && FIREWIRE
help
Enable this driver if you have a FireWire controller based
on the OHCI specification. For all practical purposes, this

View file

@ -398,7 +398,7 @@ source "drivers/gpu/drm/imagination/Kconfig"
config DRM_HYPERV
tristate "DRM Support for Hyper-V synthetic video device"
depends on DRM && PCI && MMU && HYPERV
depends on DRM && PCI && HYPERV
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_GEM_SHMEM_HELPER

View file

@ -2,7 +2,7 @@
config DRM_AMDGPU
tristate "AMD GPU"
depends on DRM && PCI && MMU
depends on DRM && PCI
depends on !UML
select FW_LOADER
select DRM_CLIENT
@ -68,7 +68,6 @@ config DRM_AMDGPU_CIK
config DRM_AMDGPU_USERPTR
bool "Always enable userptr write support"
depends on DRM_AMDGPU
depends on MMU
select HMM_MIRROR
select MMU_NOTIFIER
help

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_AST
tristate "AST server chips"
depends on DRM && PCI && MMU
depends on DRM && PCI
select DRM_CLIENT_SELECTION
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_GMA500
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
depends on DRM && PCI && X86 && MMU && HAS_IOPORT
depends on DRM && PCI && X86 && HAS_IOPORT
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION

View file

@ -2,7 +2,6 @@
config DRM_HISI_HIBMC
tristate "DRM Support for Hisilicon Hibmc"
depends on DRM && PCI
depends on MMU
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER

View file

@ -2,7 +2,7 @@
config DRM_LOONGSON
tristate "DRM support for Loongson Graphics"
depends on DRM && PCI && MMU
depends on DRM && PCI
depends on LOONGARCH || MIPS || COMPILE_TEST
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_MGAG200
tristate "Matrox G200"
depends on DRM && PCI && MMU
depends on DRM && PCI
select DRM_CLIENT_SELECTION
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_NOUVEAU
tristate "Nouveau (NVIDIA) cards"
depends on DRM && PCI && MMU
depends on DRM && PCI
select IOMMU_API
select FW_LOADER
select FW_CACHE if PM_SLEEP
@ -94,7 +94,6 @@ config DRM_NOUVEAU_SVM
bool "(EXPERIMENTAL) Enable SVM (Shared Virtual Memory) support"
depends on DEVICE_PRIVATE
depends on DRM_NOUVEAU
depends on MMU
depends on STAGING
select HMM_MIRROR
select MMU_NOTIFIER

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_QXL
tristate "QXL virtual GPU"
depends on DRM && PCI && MMU && HAS_IOPORT
depends on DRM && PCI && HAS_IOPORT
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_TTM

View file

@ -2,7 +2,7 @@
config DRM_RADEON
tristate "ATI Radeon"
depends on DRM && PCI && MMU
depends on DRM && PCI
depends on AGP || !AGP
select FW_LOADER
select DRM_CLIENT_SELECTION

View file

@ -38,7 +38,7 @@ config DRM_BOCHS
config DRM_CIRRUS_QEMU
tristate "Cirrus driver for QEMU emulated device"
depends on DRM && PCI && MMU
depends on DRM && PCI
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_GEM_SHMEM_HELPER

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config DRM_VMWGFX
tristate "DRM driver for VMware Virtual GPU"
depends on DRM && PCI && MMU
depends on DRM && PCI
depends on (X86 && HYPERVISOR_GUEST) || ARM64
select DRM_CLIENT_SELECTION
select DRM_TTM

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_XE
tristate "Intel Xe Graphics"
depends on DRM && PCI && MMU && (m || (y && KUNIT=y))
depends on DRM && PCI && (m || (y && KUNIT=y))
select INTERVAL_TREE
# we need shmfs for the swappable backing store, and in particular
# the shmem_readpage() which depends upon tmpfs

View file

@ -2024,9 +2024,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
if (!iommu->dev)
return -ENODEV;
/* Prevent binding other PCI device drivers to IOMMU devices */
iommu->dev->match_driver = false;
/* ACPI _PRT won't have an IRQ for IOMMU */
iommu->dev->irq_managed = 1;

View file

@ -96,7 +96,6 @@ config BNX2
config CNIC
tristate "QLogic CNIC support"
depends on PCI && (IPV6 || IPV6=n)
depends on MMU
select BNX2
select UIO
help

View file

@ -24,7 +24,7 @@ config ATH11K_PCI
select MHI_BUS
select QRTR
select QRTR_MHI
select PCI_PWRCTL_PWRSEQ if HAVE_PWRCTL
select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL
help
This module adds support for PCIE bus

View file

@ -7,7 +7,7 @@ config ATH12K
select MHI_BUS
select QRTR
select QRTR_MHI
select PCI_PWRCTL_PWRSEQ if HAVE_PWRCTL
select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL
help
Enable support for Qualcomm Technologies Wi-Fi 7 (IEEE
802.11be) family of chipsets, for example WCN7850 and

View file

@ -21,6 +21,7 @@ config GENERIC_PCI_IOMAP
menuconfig PCI
bool "PCI support"
depends on HAVE_PCI
depends on MMU
help
This option enables support for the PCI local bus, including
support for PCI-X and the foundations for PCI Express support.

View file

@ -369,7 +369,9 @@ void pci_bus_add_device(struct pci_dev *dev)
pdev->name);
}
dev->match_driver = !dn || of_device_is_available(dn);
if (!dn || of_device_is_available(dn))
pci_dev_allow_binding(dev);
retval = device_attach(&dev->dev);
if (retval < 0 && retval != -EPROBE_DEFER)
pci_warn(dev, "device attach failed (%d)\n", retval);

View file

@ -3,6 +3,10 @@
menu "PCI controller drivers"
depends on PCI
config PCI_HOST_COMMON
tristate
select PCI_ECAM
config PCI_AARDVARK
tristate "Aardvark PCIe controller"
depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST
@ -120,10 +124,6 @@ config PCI_FTPCI100
depends on OF
default ARCH_GEMINI
config PCI_HOST_COMMON
tristate
select PCI_ECAM
config PCI_HOST_GENERIC
tristate "Generic PCI host controller"
depends on OF

View file

@ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers"
depends on PCI
config PCIE_CADENCE
bool
tristate
config PCIE_CADENCE_HOST
bool
tristate
depends on OF
select IRQ_DOMAIN
select PCIE_CADENCE
config PCIE_CADENCE_EP
bool
tristate
depends on OF
depends on PCI_ENDPOINT
select PCIE_CADENCE
@ -43,13 +43,14 @@ config PCIE_CADENCE_PLAT_EP
different vendors SoCs.
config PCI_J721E
bool
tristate
select PCIE_CADENCE_HOST if PCI_J721E_HOST != n
select PCIE_CADENCE_EP if PCI_J721E_EP != n
config PCI_J721E_HOST
bool "TI J721E PCIe controller (host mode)"
tristate "TI J721E PCIe controller (host mode)"
depends on ARCH_K3 || COMPILE_TEST
depends on OF
select PCIE_CADENCE_HOST
select PCI_J721E
help
Say Y here if you want to support the TI J721E PCIe platform
@ -57,11 +58,10 @@ config PCI_J721E_HOST
core.
config PCI_J721E_EP
bool "TI J721E PCIe controller (endpoint mode)"
tristate "TI J721E PCIe controller (endpoint mode)"
depends on ARCH_K3 || COMPILE_TEST
depends on OF
depends on PCI_ENDPOINT
select PCIE_CADENCE_EP
select PCI_J721E
help
Say Y here if you want to support the TI J721E PCIe platform

View file

@ -15,6 +15,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
@ -27,6 +28,7 @@
#define cdns_pcie_to_rc(p) container_of(p, struct cdns_pcie_rc, pcie)
#define ENABLE_REG_SYS_2 0x108
#define ENABLE_CLR_REG_SYS_2 0x308
#define STATUS_REG_SYS_2 0x508
#define STATUS_CLR_REG_SYS_2 0x708
#define LINK_DOWN BIT(1)
@ -116,6 +118,15 @@ static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
return IRQ_HANDLED;
}
static void j721e_pcie_disable_link_irq(struct j721e_pcie *pcie)
{
u32 reg;
reg = j721e_pcie_intd_readl(pcie, ENABLE_CLR_REG_SYS_2);
reg |= pcie->linkdown_irq_regfield;
j721e_pcie_intd_writel(pcie, ENABLE_CLR_REG_SYS_2, reg);
}
static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie)
{
u32 reg;
@ -153,11 +164,7 @@ static bool j721e_pcie_link_up(struct cdns_pcie *cdns_pcie)
u32 reg;
reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_LINKSTATUS);
reg &= LINK_STATUS;
if (reg == LINK_UP_DL_COMPLETED)
return true;
return false;
return (reg & LINK_STATUS) == LINK_UP_DL_COMPLETED;
}
static const struct cdns_pcie_ops j721e_pcie_ops = {
@ -464,7 +471,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
switch (mode) {
case PCI_MODE_RC:
if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST))
if (!IS_ENABLED(CONFIG_PCI_J721E_HOST))
return -ENODEV;
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
@ -483,7 +490,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
pcie->cdns_pcie = cdns_pcie;
break;
case PCI_MODE_EP:
if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP))
if (!IS_ENABLED(CONFIG_PCI_J721E_EP))
return -ENODEV;
ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
@ -633,9 +640,22 @@ static void j721e_pcie_remove(struct platform_device *pdev)
struct j721e_pcie *pcie = platform_get_drvdata(pdev);
struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
struct device *dev = &pdev->dev;
struct cdns_pcie_ep *ep;
struct cdns_pcie_rc *rc;
if (pcie->mode == PCI_MODE_RC) {
rc = container_of(cdns_pcie, struct cdns_pcie_rc, pcie);
cdns_pcie_host_disable(rc);
} else {
ep = container_of(cdns_pcie, struct cdns_pcie_ep, pcie);
cdns_pcie_ep_disable(ep);
}
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
clk_disable_unprepare(pcie->refclk);
cdns_pcie_disable_phy(cdns_pcie);
j721e_pcie_disable_link_irq(pcie);
pm_runtime_put(dev);
pm_runtime_disable(dev);
}
@ -730,4 +750,8 @@ static struct platform_driver j721e_pcie_driver = {
.pm = pm_sleep_ptr(&j721e_pcie_pm_ops),
},
};
builtin_platform_driver(j721e_pcie_driver);
module_platform_driver(j721e_pcie_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCIe controller driver for TI's J721E and related SoCs");
MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");

View file

@ -6,12 +6,14 @@
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pci-epc.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>
#include "pcie-cadence.h"
#include "../../pci.h"
#define CDNS_PCIE_EP_MIN_APERTURE 128 /* 128 bytes */
#define CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE 0x1
@ -220,10 +222,11 @@ static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
clear_bit(r, &ep->ob_region_map);
}
static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 mmc)
static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 nr_irqs)
{
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = &ep->pcie;
u8 mmc = order_base_2(nr_irqs);
u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET;
u16 flags;
@ -262,7 +265,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
*/
mme = FIELD_GET(PCI_MSI_FLAGS_QSIZE, flags);
return mme;
return 1 << mme;
}
static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
@ -281,12 +284,11 @@ static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
val &= PCI_MSIX_FLAGS_QSIZE;
return val;
return val + 1;
}
static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
u16 interrupts, enum pci_barno bir,
u32 offset)
u16 nr_irqs, enum pci_barno bir, u32 offset)
{
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = &ep->pcie;
@ -298,7 +300,7 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
reg = cap + PCI_MSIX_FLAGS;
val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
val &= ~PCI_MSIX_FLAGS_QSIZE;
val |= interrupts;
val |= nr_irqs - 1; /* encoded as N-1 */
cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
/* Set MSI-X BAR and offset */
@ -308,7 +310,7 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
/* Set PBA BAR and offset. BAR must match MSI-X BAR */
reg = cap + PCI_MSIX_PBA;
val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
val = (offset + (nr_irqs * PCI_MSIX_ENTRY_SIZE)) | bir;
cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
return 0;
@ -337,10 +339,10 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn, u8 intx,
if (is_asserted) {
ep->irq_pending |= BIT(intx);
msg_code = MSG_CODE_ASSERT_INTA + intx;
msg_code = PCIE_MSG_CODE_ASSERT_INTA + intx;
} else {
ep->irq_pending &= ~BIT(intx);
msg_code = MSG_CODE_DEASSERT_INTA + intx;
msg_code = PCIE_MSG_CODE_DEASSERT_INTA + intx;
}
spin_lock_irqsave(&ep->lock, flags);
@ -644,6 +646,17 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
.get_features = cdns_pcie_ep_get_features,
};
void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
{
struct device *dev = ep->pcie.dev;
struct pci_epc *epc = to_pci_epc(dev);
pci_epc_deinit_notify(epc);
pci_epc_mem_free_addr(epc, ep->irq_phys_addr, ep->irq_cpu_addr,
SZ_128K);
pci_epc_mem_exit(epc);
}
EXPORT_SYMBOL_GPL(cdns_pcie_ep_disable);
int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
{
@ -751,3 +764,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
return ret;
}
EXPORT_SYMBOL_GPL(cdns_pcie_ep_setup);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cadence PCIe endpoint controller driver");
MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@free-electrons.com>");

View file

@ -5,6 +5,7 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/list_sort.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
@ -72,6 +73,7 @@ void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
return rc->cfg_base + (where & 0xfff);
}
EXPORT_SYMBOL_GPL(cdns_pci_map_bus);
static struct pci_ops cdns_pcie_host_ops = {
.map_bus = cdns_pci_map_bus,
@ -150,6 +152,14 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie)
return ret;
}
static void cdns_pcie_host_disable_ptm_response(struct cdns_pcie *pcie)
{
u32 val;
val = cdns_pcie_readl(pcie, CDNS_PCIE_LM_PTM_CTRL);
cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val & ~CDNS_PCIE_LM_TPM_CTRL_PTMRSEN);
}
static void cdns_pcie_host_enable_ptm_response(struct cdns_pcie *pcie)
{
u32 val;
@ -175,6 +185,26 @@ static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
return ret;
}
static void cdns_pcie_host_deinit_root_port(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
u32 value, ctrl;
cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, 0xffff);
cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0xff);
cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0xff);
cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, 0xffffffff);
cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, 0xffff);
ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
value = ~(CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS);
cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
}
static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
@ -391,6 +421,32 @@ static int cdns_pcie_host_dma_ranges_cmp(void *priv, const struct list_head *a,
return resource_size(entry2->res) - resource_size(entry1->res);
}
static void cdns_pcie_host_unmap_dma_ranges(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
enum cdns_pcie_rp_bar bar;
u32 value;
/* Reset inbound configuration for all BARs which were being used */
for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
if (rc->avail_ib_bar[bar])
continue;
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), 0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), 0);
if (bar == RP_NO_BAR)
continue;
value = ~(LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar) |
LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar) |
LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar) |
LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar) |
LM_RC_BAR_CFG_APERTURE(bar, bar_aperture_mask[bar] + 2));
cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
}
}
static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
@ -428,6 +484,29 @@ static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
return 0;
}
static void cdns_pcie_host_deinit_address_translation(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
struct resource_entry *entry;
int r;
cdns_pcie_host_unmap_dma_ranges(rc);
/*
* Reset outbound region 0 which was reserved for configuration space
* accesses.
*/
cdns_pcie_reset_outbound_region(pcie, 0);
/* Reset rest of the outbound regions */
r = 1;
resource_list_for_each_entry(entry, &bridge->windows) {
cdns_pcie_reset_outbound_region(pcie, r);
r++;
}
}
static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
@ -485,6 +564,12 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
return cdns_pcie_host_map_dma_ranges(rc);
}
static void cdns_pcie_host_deinit(struct cdns_pcie_rc *rc)
{
cdns_pcie_host_deinit_address_translation(rc);
cdns_pcie_host_deinit_root_port(rc);
}
int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
{
int err;
@ -495,6 +580,15 @@ int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
return cdns_pcie_host_init_address_translation(rc);
}
EXPORT_SYMBOL_GPL(cdns_pcie_host_init);
static void cdns_pcie_host_link_disable(struct cdns_pcie_rc *rc)
{
struct cdns_pcie *pcie = &rc->pcie;
cdns_pcie_stop_link(pcie);
cdns_pcie_host_disable_ptm_response(pcie);
}
int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
{
@ -519,6 +613,20 @@ int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
return 0;
}
EXPORT_SYMBOL_GPL(cdns_pcie_host_link_setup);
void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
{
struct pci_host_bridge *bridge;
bridge = pci_host_bridge_from_priv(rc);
pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
cdns_pcie_host_deinit(rc);
cdns_pcie_host_link_disable(rc);
}
EXPORT_SYMBOL_GPL(cdns_pcie_host_disable);
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
{
@ -570,14 +678,10 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
if (!bridge->ops)
bridge->ops = &cdns_pcie_host_ops;
ret = pci_host_probe(bridge);
if (ret < 0)
goto err_init;
return 0;
err_init:
pm_runtime_put_sync(dev);
return ret;
return pci_host_probe(bridge);
}
EXPORT_SYMBOL_GPL(cdns_pcie_host_setup);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cadence PCIe host controller driver");
MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@free-electrons.com>");

View file

@ -4,6 +4,7 @@
// Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include "pcie-cadence.h"
@ -23,6 +24,7 @@ void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie)
cdns_pcie_writel(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP, ltssm_control_cap);
}
EXPORT_SYMBOL_GPL(cdns_pcie_detect_quiet_min_delay_set);
void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
u32 r, bool is_io,
@ -100,6 +102,7 @@ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
}
EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region);
void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
u8 busnr, u8 fn,
@ -134,6 +137,7 @@ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
}
EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region_for_normal_msg);
void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
{
@ -146,6 +150,7 @@ void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0);
}
EXPORT_SYMBOL_GPL(cdns_pcie_reset_outbound_region);
void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
{
@ -156,6 +161,7 @@ void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
phy_exit(pcie->phy[i]);
}
}
EXPORT_SYMBOL_GPL(cdns_pcie_disable_phy);
int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
{
@ -184,6 +190,7 @@ int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
return ret;
}
EXPORT_SYMBOL_GPL(cdns_pcie_enable_phy);
int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
{
@ -243,6 +250,7 @@ int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
return ret;
}
EXPORT_SYMBOL_GPL(cdns_pcie_init_phy);
static int cdns_pcie_suspend_noirq(struct device *dev)
{
@ -271,3 +279,7 @@ const struct dev_pm_ops cdns_pcie_pm_ops = {
NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq,
cdns_pcie_resume_noirq)
};
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cadence PCIe controller driver");
MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@free-electrons.com>");

View file

@ -250,17 +250,6 @@ struct cdns_pcie_rp_ib_bar {
struct cdns_pcie;
enum cdns_pcie_msg_code {
MSG_CODE_ASSERT_INTA = 0x20,
MSG_CODE_ASSERT_INTB = 0x21,
MSG_CODE_ASSERT_INTC = 0x22,
MSG_CODE_ASSERT_INTD = 0x23,
MSG_CODE_DEASSERT_INTA = 0x24,
MSG_CODE_DEASSERT_INTB = 0x25,
MSG_CODE_DEASSERT_INTC = 0x26,
MSG_CODE_DEASSERT_INTD = 0x27,
};
enum cdns_pcie_msg_routing {
/* Route to Root Complex */
MSG_ROUTING_TO_RC,
@ -519,10 +508,11 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
return true;
}
#ifdef CONFIG_PCIE_CADENCE_HOST
#if IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)
int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc);
int cdns_pcie_host_init(struct cdns_pcie_rc *rc);
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
void cdns_pcie_host_disable(struct cdns_pcie_rc *rc);
void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
int where);
#else
@ -541,6 +531,10 @@ static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
return 0;
}
static inline void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
{
}
static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
int where)
{
@ -548,13 +542,18 @@ static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int d
}
#endif
#ifdef CONFIG_PCIE_CADENCE_EP
#if IS_ENABLED(CONFIG_PCIE_CADENCE_EP)
int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep);
void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep);
#else
static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
{
return 0;
}
static inline void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
{
}
#endif
void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie);

View file

@ -118,12 +118,12 @@ static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;
}
static int dra7xx_pcie_link_up(struct dw_pcie *pci)
static bool dra7xx_pcie_link_up(struct dw_pcie *pci)
{
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS);
return !!(reg & LINK_UP);
return reg & LINK_UP;
}
static void dra7xx_pcie_stop_link(struct dw_pcie *pci)

View file

@ -209,12 +209,12 @@ static struct pci_ops exynos_pci_ops = {
.write = exynos_pcie_wr_own_conf,
};
static int exynos_pcie_link_up(struct dw_pcie *pci)
static bool exynos_pcie_link_up(struct dw_pcie *pci)
{
struct exynos_pcie *ep = to_exynos_pcie(pci);
u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP);
return (val & PCIE_ELBI_XMLH_LINKUP);
return val & PCIE_ELBI_XMLH_LINKUP;
}
static int exynos_pcie_host_init(struct dw_pcie_rp *pp)

View file

@ -45,9 +45,14 @@
#define IMX95_PCIE_PHY_GEN_CTRL 0x0
#define IMX95_PCIE_REF_USE_PAD BIT(17)
#define IMX95_PCIE_PHY_MPLLA_CTRL 0x10
#define IMX95_PCIE_PHY_MPLL_STATE BIT(30)
#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_PCIE_SS_RW_REG_1 0xf4
#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
#define IMX95_PE0_GEN_CTRL_1 0x1050
#define IMX95_PCIE_DEVICE_TYPE GENMASK(3, 0)
@ -71,6 +76,9 @@
#define IMX95_SID_MASK GENMASK(5, 0)
#define IMX95_MAX_LUT 32
#define IMX95_PCIE_RST_CTRL 0x3010
#define IMX95_PCIE_COLD_RST BIT(0)
#define to_imx_pcie(x) dev_get_drvdata((x)->dev)
enum imx_pcie_variants {
@ -91,7 +99,7 @@ enum imx_pcie_variants {
};
#define IMX_PCIE_FLAG_IMX_PHY BIT(0)
#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE BIT(1)
#define IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND BIT(1)
#define IMX_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2)
#define IMX_PCIE_FLAG_HAS_PHYDRV BIT(3)
#define IMX_PCIE_FLAG_HAS_APP_RESET BIT(4)
@ -105,6 +113,7 @@ enum imx_pcie_variants {
*/
#define IMX_PCIE_FLAG_BROKEN_SUSPEND BIT(9)
#define IMX_PCIE_FLAG_HAS_LUT BIT(10)
#define IMX_PCIE_FLAG_8GT_ECN_ERR051586 BIT(11)
#define imx_check_flag(pci, val) (pci->drvdata->flags & val)
@ -126,9 +135,15 @@ struct imx_pcie_drvdata {
int (*init_phy)(struct imx_pcie *pcie);
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
int (*core_reset)(struct imx_pcie *pcie, bool assert);
int (*wait_pll_lock)(struct imx_pcie *pcie);
const struct dw_pcie_host_ops *ops;
};
struct imx_lut_data {
u32 data1;
u32 data2;
};
struct imx_pcie {
struct dw_pcie *pci;
struct gpio_desc *reset_gpiod;
@ -148,6 +163,8 @@ struct imx_pcie {
struct regulator *vph;
void __iomem *phy_base;
/* LUT data for pcie */
struct imx_lut_data luts[IMX95_MAX_LUT];
/* power domain for pcie */
struct device *pd_pcie;
/* power domain for pcie phy */
@ -224,6 +241,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
{
/*
* ERR051624: The Controller Without Vaux Cannot Exit L23 Ready
* Through Beacon or PERST# De-assertion
*
* When the auxiliary power is not available, the controller
* cannot exit from L23 Ready with beacon or PERST# de-assertion
* when main power is not removed.
*
* Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
*/
regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
IMX95_PCIE_SYS_AUX_PWR_DET);
regmap_update_bits(imx_pcie->iomuxc_gpr,
IMX95_PCIE_SS_RW_REG_0,
IMX95_PCIE_PHY_CR_PARA_SEL,
@ -460,6 +490,23 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
dev_err(dev, "PCIe PLL lock timeout\n");
}
static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
{
u32 val;
struct device *dev = imx_pcie->pci->dev;
if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
IMX95_PCIE_PHY_MPLLA_CTRL, val,
val & IMX95_PCIE_PHY_MPLL_STATE,
PHY_PLL_LOCK_WAIT_USLEEP_MAX,
PHY_PLL_LOCK_WAIT_TIMEOUT)) {
dev_err(dev, "PCIe PLL lock timeout\n");
return -ETIMEDOUT;
}
return 0;
}
static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)
{
unsigned long phy_rate = 0;
@ -773,6 +820,43 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
return 0;
}
static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
{
u32 val;
if (assert) {
/*
* From i.MX95 PCIe PHY perspective, the COLD reset toggle
* should be complete after power-up by the following sequence.
* > 10us(at power-up)
* > 10ns(warm reset)
* |<------------>|
* ______________
* phy_reset ____/ \________________
* ____________
* ref_clk_en_______________________/
* Toggle COLD reset aligned with this sequence for i.MX95 PCIe.
*/
regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
IMX95_PCIE_COLD_RST);
/*
* Make sure the write to IMX95_PCIE_RST_CTRL is flushed to the
* hardware by doing a read. Otherwise, there is no guarantee
* that the write has reached the hardware before udelay().
*/
regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
&val);
udelay(15);
regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
IMX95_PCIE_COLD_RST);
regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
&val);
udelay(10);
}
return 0;
}
static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
{
reset_control_assert(imx_pcie->pciephy_reset);
@ -860,6 +944,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
u32 tmp;
int ret;
if (!(imx_pcie->drvdata->flags &
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND)) {
imx_pcie_ltssm_enable(dev);
return 0;
}
/*
* Force Gen1 operation when starting the link. In case the link is
* started in Gen2 mode, there is a possibility the devices on the
@ -875,11 +965,11 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
/* Start LTSSM. */
imx_pcie_ltssm_enable(dev);
ret = dw_pcie_wait_for_link(pci);
if (ret)
goto err_reset_phy;
if (pci->max_link_speed > 1) {
ret = dw_pcie_wait_for_link(pci);
if (ret)
goto err_reset_phy;
/* Allow faster modes after the link is up */
dw_pcie_dbi_ro_wr_en(pci);
tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
@ -896,34 +986,15 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
dw_pcie_dbi_ro_wr_dis(pci);
if (imx_pcie->drvdata->flags &
IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
/*
* On i.MX7, DIRECT_SPEED_CHANGE behaves differently
* from i.MX6 family when no link speed transition
* occurs and we go Gen1 -> yep, Gen1. The difference
* is that, in such case, it will not be cleared by HW
* which will cause the following code to report false
* failure.
*/
ret = imx_pcie_wait_for_speed_change(imx_pcie);
if (ret) {
dev_err(dev, "Failed to bring link up!\n");
goto err_reset_phy;
}
}
/* Make sure link training is finished as well! */
ret = dw_pcie_wait_for_link(pci);
if (ret)
ret = imx_pcie_wait_for_speed_change(imx_pcie);
if (ret) {
dev_err(dev, "Failed to bring link up!\n");
goto err_reset_phy;
}
} else {
dev_info(dev, "Link: Only Gen1 is enabled\n");
}
tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);
return 0;
err_reset_phy:
@ -1182,6 +1253,12 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
goto err_phy_off;
}
if (imx_pcie->drvdata->wait_pll_lock) {
ret = imx_pcie->drvdata->wait_pll_lock(imx_pcie);
if (ret < 0)
goto err_phy_off;
}
imx_setup_phy_mpll(imx_pcie);
return 0;
@ -1214,6 +1291,32 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
regulator_disable(imx_pcie->vpcie);
}
static void imx_pcie_host_post_init(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx_pcie *imx_pcie = to_imx_pcie(pci);
u32 val;
if (imx_pcie->drvdata->flags & IMX_PCIE_FLAG_8GT_ECN_ERR051586) {
/*
* ERR051586: Compliance with 8GT/s Receiver Impedance ECN
*
* The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL]
* is 1 which makes receiver non-compliant with the ZRX-DC
* parameter for 2.5 GT/s when operating at 8 GT/s or higher.
* It causes unnecessary timeout in L1.
*
* Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL]
* to 0.
*/
dw_pcie_dbi_ro_wr_en(pci);
val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
dw_pcie_dbi_ro_wr_dis(pci);
}
}
/*
* In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2
* register is reserved, so the generic DWC implementation of sending the
@ -1239,6 +1342,7 @@ static const struct dw_pcie_host_ops imx_pcie_host_ops = {
static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {
.init = imx_pcie_host_init,
.deinit = imx_pcie_host_exit,
.post_init = imx_pcie_host_post_init,
};
static const struct dw_pcie_ops dw_pcie_ops = {
@ -1350,6 +1454,7 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie,
dev_err(dev, "failed to initialize endpoint\n");
return ret;
}
imx_pcie_host_post_init(pp);
ret = dw_pcie_ep_init_registers(ep);
if (ret) {
@ -1386,6 +1491,42 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
}
}
static void imx_pcie_lut_save(struct imx_pcie *imx_pcie)
{
u32 data1, data2;
int i;
for (i = 0; i < IMX95_MAX_LUT; i++) {
regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL,
IMX95_PEO_LUT_RWA | i);
regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1);
regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2);
if (data1 & IMX95_PE0_LUT_VLD) {
imx_pcie->luts[i].data1 = data1;
imx_pcie->luts[i].data2 = data2;
} else {
imx_pcie->luts[i].data1 = 0;
imx_pcie->luts[i].data2 = 0;
}
}
}
static void imx_pcie_lut_restore(struct imx_pcie *imx_pcie)
{
int i;
for (i = 0; i < IMX95_MAX_LUT; i++) {
if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0)
continue;
regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1,
imx_pcie->luts[i].data1);
regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2,
imx_pcie->luts[i].data2);
regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i);
}
}
static int imx_pcie_suspend_noirq(struct device *dev)
{
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
@ -1394,6 +1535,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)
return 0;
imx_pcie_msi_save_restore(imx_pcie, true);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_save(imx_pcie);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
/*
* The minimum for a workaround would be to set PERST# and to
@ -1438,6 +1581,8 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (ret)
return ret;
}
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_restore(imx_pcie);
imx_pcie_msi_save_restore(imx_pcie, false);
return 0;
@ -1649,7 +1794,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6Q] = {
.variant = IMX6Q,
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_BROKEN_SUSPEND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.dbi_length = 0x200,
@ -1665,7 +1810,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6SX] = {
.variant = IMX6SX,
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.gpr = "fsl,imx6q-iomuxc-gpr",
.ltssm_off = IOMUXC_GPR12,
@ -1680,7 +1825,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6QP] = {
.variant = IMX6QP,
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.dbi_length = 0x200,
.gpr = "fsl,imx6q-iomuxc-gpr",
@ -1747,12 +1892,15 @@ static const struct imx_pcie_drvdata drvdata[] = {
.variant = IMX95,
.flags = IMX_PCIE_FLAG_HAS_SERDES |
IMX_PCIE_FLAG_HAS_LUT |
IMX_PCIE_FLAG_8GT_ECN_ERR051586 |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.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,
.core_reset = imx95_pcie_core_reset,
.init_phy = imx95_pcie_init_phy,
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
},
[IMX8MQ_EP] = {
.variant = IMX8MQ_EP,
@ -1799,12 +1947,15 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX95_EP] = {
.variant = IMX95_EP,
.flags = IMX_PCIE_FLAG_HAS_SERDES |
IMX_PCIE_FLAG_8GT_ECN_ERR051586 |
IMX_PCIE_FLAG_SUPPORT_64BIT,
.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,
.core_reset = imx95_pcie_core_reset,
.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
.epc_features = &imx95_pcie_epc_features,
.mode = DW_PCIE_EP_TYPE,
},

View file

@ -492,13 +492,12 @@ static struct pci_ops ks_pcie_ops = {
* @pci: A pointer to the dw_pcie structure which holds the DesignWare PCIe host
* controller driver information.
*/
static int ks_pcie_link_up(struct dw_pcie *pci)
static bool ks_pcie_link_up(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0);
val &= PORT_LOGIC_LTSSM_STATE_MASK;
return (val == PORT_LOGIC_LTSSM_STATE_L0);
return (val & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L0;
}
static void ks_pcie_stop_link(struct dw_pcie *pci)

View file

@ -335,7 +335,7 @@ static struct pci_ops meson_pci_ops = {
.write = pci_generic_config_write,
};
static int meson_pcie_link_up(struct dw_pcie *pci)
static bool meson_pcie_link_up(struct dw_pcie *pci)
{
struct meson_pcie *mp = to_meson_pcie(pci);
struct device *dev = pci->dev;
@ -363,7 +363,7 @@ static int meson_pcie_link_up(struct dw_pcie *pci)
dev_dbg(dev, "speed_okay\n");
if (smlh_up && rdlh_up && ltssm_up && speed_okay)
return 1;
return true;
cnt++;
@ -371,7 +371,7 @@ static int meson_pcie_link_up(struct dw_pcie *pci)
} while (cnt < WAIT_LINKUP_TIMEOUT);
dev_err(dev, "error: wait linkup timeout\n");
return 0;
return false;
}
static int meson_pcie_host_init(struct dw_pcie_rp *pp)

View file

@ -139,7 +139,7 @@ static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie)
return ret;
}
static int armada8k_pcie_link_up(struct dw_pcie *pci)
static bool armada8k_pcie_link_up(struct dw_pcie *pci)
{
u32 reg;
u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP;
@ -147,10 +147,10 @@ static int armada8k_pcie_link_up(struct dw_pcie *pci)
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG);
if ((reg & mask) == mask)
return 1;
return true;
dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg);
return 0;
return false;
}
static int armada8k_pcie_start_link(struct dw_pcie *pci)

View file

@ -642,16 +642,262 @@ static void dwc_pcie_ltssm_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
&dwc_pcie_ltssm_status_ops);
}
static int dw_pcie_ptm_check_capability(void *drvdata)
{
struct dw_pcie *pci = drvdata;
pci->ptm_vsec_offset = dw_pcie_find_ptm_capability(pci);
return pci->ptm_vsec_offset;
}
static int dw_pcie_ptm_context_update_write(void *drvdata, u8 mode)
{
struct dw_pcie *pci = drvdata;
u32 val;
if (mode == PCIE_PTM_CONTEXT_UPDATE_AUTO) {
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
val |= PTM_REQ_AUTO_UPDATE_ENABLED;
dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
} else if (mode == PCIE_PTM_CONTEXT_UPDATE_MANUAL) {
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
val &= ~PTM_REQ_AUTO_UPDATE_ENABLED;
val |= PTM_REQ_START_UPDATE;
dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
} else {
return -EINVAL;
}
return 0;
}
static int dw_pcie_ptm_context_update_read(void *drvdata, u8 *mode)
{
struct dw_pcie *pci = drvdata;
u32 val;
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
if (FIELD_GET(PTM_REQ_AUTO_UPDATE_ENABLED, val))
*mode = PCIE_PTM_CONTEXT_UPDATE_AUTO;
else
/*
* PTM_REQ_START_UPDATE is a self clearing register bit. So if
* PTM_REQ_AUTO_UPDATE_ENABLED is not set, then it implies that
* manual update is used.
*/
*mode = PCIE_PTM_CONTEXT_UPDATE_MANUAL;
return 0;
}
static int dw_pcie_ptm_context_valid_write(void *drvdata, bool valid)
{
struct dw_pcie *pci = drvdata;
u32 val;
if (valid) {
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
val |= PTM_RES_CCONTEXT_VALID;
dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
} else {
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
val &= ~PTM_RES_CCONTEXT_VALID;
dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val);
}
return 0;
}
static int dw_pcie_ptm_context_valid_read(void *drvdata, bool *valid)
{
struct dw_pcie *pci = drvdata;
u32 val;
val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL);
*valid = !!FIELD_GET(PTM_RES_CCONTEXT_VALID, val);
return 0;
}
static int dw_pcie_ptm_local_clock_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static int dw_pcie_ptm_master_clock_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static int dw_pcie_ptm_t1_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static int dw_pcie_ptm_t2_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static int dw_pcie_ptm_t3_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static int dw_pcie_ptm_t4_read(void *drvdata, u64 *clock)
{
struct dw_pcie *pci = drvdata;
u32 msb, lsb;
do {
msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB);
lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB);
} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB));
*clock = ((u64) msb) << 32 | lsb;
return 0;
}
static bool dw_pcie_ptm_context_update_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
}
static bool dw_pcie_ptm_context_valid_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
}
static bool dw_pcie_ptm_local_clock_visible(void *drvdata)
{
/* PTM local clock is always visible */
return true;
}
static bool dw_pcie_ptm_master_clock_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
}
static bool dw_pcie_ptm_t1_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
}
static bool dw_pcie_ptm_t2_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
}
static bool dw_pcie_ptm_t3_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_RC_TYPE) ? true : false;
}
static bool dw_pcie_ptm_t4_visible(void *drvdata)
{
struct dw_pcie *pci = drvdata;
return (pci->mode == DW_PCIE_EP_TYPE) ? true : false;
}
const struct pcie_ptm_ops dw_pcie_ptm_ops = {
.check_capability = dw_pcie_ptm_check_capability,
.context_update_write = dw_pcie_ptm_context_update_write,
.context_update_read = dw_pcie_ptm_context_update_read,
.context_valid_write = dw_pcie_ptm_context_valid_write,
.context_valid_read = dw_pcie_ptm_context_valid_read,
.local_clock_read = dw_pcie_ptm_local_clock_read,
.master_clock_read = dw_pcie_ptm_master_clock_read,
.t1_read = dw_pcie_ptm_t1_read,
.t2_read = dw_pcie_ptm_t2_read,
.t3_read = dw_pcie_ptm_t3_read,
.t4_read = dw_pcie_ptm_t4_read,
.context_update_visible = dw_pcie_ptm_context_update_visible,
.context_valid_visible = dw_pcie_ptm_context_valid_visible,
.local_clock_visible = dw_pcie_ptm_local_clock_visible,
.master_clock_visible = dw_pcie_ptm_master_clock_visible,
.t1_visible = dw_pcie_ptm_t1_visible,
.t2_visible = dw_pcie_ptm_t2_visible,
.t3_visible = dw_pcie_ptm_t3_visible,
.t4_visible = dw_pcie_ptm_t4_visible,
};
void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
{
if (!pci->debugfs)
return;
pcie_ptm_destroy_debugfs(pci->ptm_debugfs);
dwc_pcie_rasdes_debugfs_deinit(pci);
debugfs_remove_recursive(pci->debugfs->debug_dir);
}
void dwc_pcie_debugfs_init(struct dw_pcie *pci)
void dwc_pcie_debugfs_init(struct dw_pcie *pci, enum dw_pcie_device_mode mode)
{
char dirname[DWC_DEBUGFS_BUF_MAX];
struct device *dev = pci->dev;
@ -674,4 +920,8 @@ void dwc_pcie_debugfs_init(struct dw_pcie *pci)
err);
dwc_pcie_ltssm_debugfs_init(pci, dir);
pci->mode = mode;
pci->ptm_debugfs = pcie_ptm_create_debugfs(pci->dev, pci,
&dw_pcie_ptm_ops);
}

View file

@ -256,11 +256,11 @@ static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,
return offset;
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> PCI_REBAR_CTRL_NBAR_SHIFT;
nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
bar_index = reg & PCI_REBAR_CTRL_BAR_IDX;
bar_index = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, reg);
if (bar_index == bar)
return offset;
}
@ -532,15 +532,16 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
val = FIELD_GET(PCI_MSI_FLAGS_QSIZE, val);
return val;
return 1 << val;
}
static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
u8 interrupts)
u8 nr_irqs)
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct dw_pcie_ep_func *ep_func;
u8 mmc = order_base_2(nr_irqs);
u32 val, reg;
ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
@ -550,7 +551,7 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
reg = ep_func->msi_cap + PCI_MSI_FLAGS;
val = dw_pcie_ep_readw_dbi(ep, func_no, reg);
val &= ~PCI_MSI_FLAGS_QMASK;
val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, interrupts);
val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, mmc);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_ep_writew_dbi(ep, func_no, reg, val);
dw_pcie_dbi_ro_wr_dis(pci);
@ -575,11 +576,11 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
val &= PCI_MSIX_FLAGS_QSIZE;
return val;
return val + 1;
}
static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
u16 interrupts, enum pci_barno bir, u32 offset)
u16 nr_irqs, enum pci_barno bir, u32 offset)
{
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@ -595,7 +596,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
reg = ep_func->msix_cap + PCI_MSIX_FLAGS;
val = dw_pcie_ep_readw_dbi(ep, func_no, reg);
val &= ~PCI_MSIX_FLAGS_QSIZE;
val |= interrupts;
val |= nr_irqs - 1; /* encoded as N-1 */
dw_pcie_writew_dbi(pci, reg, val);
reg = ep_func->msix_cap + PCI_MSIX_TABLE;
@ -603,7 +604,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
reg = ep_func->msix_cap + PCI_MSIX_PBA;
val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
val = (offset + (nr_irqs * PCI_MSIX_ENTRY_SIZE)) | bir;
dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
dw_pcie_dbi_ro_wr_dis(pci);
@ -671,7 +672,7 @@ static const struct pci_epc_ops epc_ops = {
* @ep: DWC EP device
* @func_no: Function number of the endpoint
*
* Return: 0 if success, errono otherwise.
* Return: 0 if success, errno otherwise.
*/
int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no)
{
@ -690,7 +691,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_intx_irq);
* @func_no: Function number of the endpoint
* @interrupt_num: Interrupt number to be raised
*
* Return: 0 if success, errono otherwise.
* Return: 0 if success, errno otherwise.
*/
int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
u8 interrupt_num)
@ -875,8 +876,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
if (offset) {
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
PCI_REBAR_CTRL_NBAR_SHIFT;
nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);
/*
* PCIe r6.0, sec 7.8.6.2 require us to support at least one
@ -897,7 +897,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
* is why RESBAR_CAP_REG is written here.
*/
val = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
bar = val & PCI_REBAR_CTRL_BAR_IDX;
bar = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, val);
if (ep->epf_bar[bar])
pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val);
else
@ -1013,7 +1013,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
dw_pcie_ep_init_non_sticky_registers(pci);
dwc_pcie_debugfs_init(pci);
dwc_pcie_debugfs_init(pci, DW_PCIE_EP_TYPE);
return 0;

View file

@ -523,6 +523,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
dw_pcie_iatu_detect(pci);
if (pci->num_lanes < 1)
pci->num_lanes = dw_pcie_link_get_max_link_width(pci);
ret = of_pci_get_equalization_presets(dev, &pp->presets, pci->num_lanes);
if (ret)
goto err_free_msi;
/*
* Allocate the resource for MSG TLP before programming the iATU
* outbound window in dw_pcie_setup_rc(). Since the allocation depends
@ -567,7 +574,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
if (pp->ops->post_init)
pp->ops->post_init(pp);
dwc_pcie_debugfs_init(pci);
dwc_pcie_debugfs_init(pci, DW_PCIE_RC_TYPE);
return 0;
@ -828,6 +835,77 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
return 0;
}
static void dw_pcie_program_presets(struct dw_pcie_rp *pp, enum pci_bus_speed speed)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
u8 lane_eq_offset, lane_reg_size, cap_id;
u8 *presets;
u32 cap;
int i;
if (speed == PCIE_SPEED_8_0GT) {
presets = (u8 *)pp->presets.eq_presets_8gts;
lane_eq_offset = PCI_SECPCI_LE_CTRL;
cap_id = PCI_EXT_CAP_ID_SECPCI;
/* For data rate of 8 GT/S each lane equalization control is 16bits wide*/
lane_reg_size = 0x2;
} else if (speed == PCIE_SPEED_16_0GT) {
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_16GTS - 1];
lane_eq_offset = PCI_PL_16GT_LE_CTRL;
cap_id = PCI_EXT_CAP_ID_PL_16GT;
lane_reg_size = 0x1;
} else if (speed == PCIE_SPEED_32_0GT) {
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_32GTS - 1];
lane_eq_offset = PCI_PL_32GT_LE_CTRL;
cap_id = PCI_EXT_CAP_ID_PL_32GT;
lane_reg_size = 0x1;
} else if (speed == PCIE_SPEED_64_0GT) {
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_64GTS - 1];
lane_eq_offset = PCI_PL_64GT_LE_CTRL;
cap_id = PCI_EXT_CAP_ID_PL_64GT;
lane_reg_size = 0x1;
} else {
return;
}
if (presets[0] == PCI_EQ_RESV)
return;
cap = dw_pcie_find_ext_capability(pci, cap_id);
if (!cap)
return;
/*
* Write preset values to the registers byte-by-byte for the given
* number of lanes and register size.
*/
for (i = 0; i < pci->num_lanes * lane_reg_size; i++)
dw_pcie_writeb_dbi(pci, cap + lane_eq_offset + i, presets[i]);
}
static void dw_pcie_config_presets(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed];
/*
* Lane equalization settings need to be applied for all data rates the
* controller supports and for all supported lanes.
*/
if (speed >= PCIE_SPEED_8_0GT)
dw_pcie_program_presets(pp, PCIE_SPEED_8_0GT);
if (speed >= PCIE_SPEED_16_0GT)
dw_pcie_program_presets(pp, PCIE_SPEED_16_0GT);
if (speed >= PCIE_SPEED_32_0GT)
dw_pcie_program_presets(pp, PCIE_SPEED_32_0GT);
if (speed >= PCIE_SPEED_64_0GT)
dw_pcie_program_presets(pp, PCIE_SPEED_64_0GT);
}
int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@ -881,6 +959,7 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
dw_pcie_config_presets(pp);
/*
* If the platform provides its own child bus config accesses, it means
* the platform uses its own address translation component rather than

View file

@ -54,6 +54,14 @@ static const char * const dw_pcie_core_rsts[DW_PCIE_NUM_CORE_RSTS] = {
[DW_PCIE_PWR_RST] = "pwr",
};
static const struct dwc_pcie_vsec_id dwc_pcie_ptm_vsec_ids[] = {
{ .vendor_id = PCI_VENDOR_ID_QCOM, /* EP */
.vsec_id = 0x03, .vsec_rev = 0x1 },
{ .vendor_id = PCI_VENDOR_ID_QCOM, /* RC */
.vsec_id = 0x04, .vsec_rev = 0x1 },
{ }
};
static int dw_pcie_get_clocks(struct dw_pcie *pci)
{
int i, ret;
@ -330,6 +338,12 @@ u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci)
}
EXPORT_SYMBOL_GPL(dw_pcie_find_rasdes_capability);
u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci)
{
return dw_pcie_find_vsec_capability(pci, dwc_pcie_ptm_vsec_ids);
}
EXPORT_SYMBOL_GPL(dw_pcie_find_ptm_capability);
int dw_pcie_read(void __iomem *addr, int size, u32 *val)
{
if (!IS_ALIGNED((uintptr_t)addr, size)) {
@ -711,7 +725,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
}
EXPORT_SYMBOL_GPL(dw_pcie_wait_for_link);
int dw_pcie_link_up(struct dw_pcie *pci)
bool dw_pcie_link_up(struct dw_pcie *pci)
{
u32 val;
@ -781,6 +795,14 @@ static void dw_pcie_link_set_max_speed(struct dw_pcie *pci)
}
int dw_pcie_link_get_max_link_width(struct dw_pcie *pci)
{
u8 cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
u32 lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP);
return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap);
}
static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)
{
u32 lnkcap, lwsc, plc;
@ -797,22 +819,19 @@ static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)
/* Set link width speed control register */
lwsc = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
lwsc &= ~PORT_LOGIC_LINK_WIDTH_MASK;
lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES;
switch (num_lanes) {
case 1:
plc |= PORT_LINK_MODE_1_LANES;
lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES;
break;
case 2:
plc |= PORT_LINK_MODE_2_LANES;
lwsc |= PORT_LOGIC_LINK_WIDTH_2_LANES;
break;
case 4:
plc |= PORT_LINK_MODE_4_LANES;
lwsc |= PORT_LOGIC_LINK_WIDTH_4_LANES;
break;
case 8:
plc |= PORT_LINK_MODE_8_LANES;
lwsc |= PORT_LOGIC_LINK_WIDTH_8_LANES;
break;
default:
dev_err(pci->dev, "num-lanes %u: invalid value\n", num_lanes);

View file

@ -25,6 +25,8 @@
#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
#include "../../pci.h"
/* DWC PCIe IP-core versions (native support since v4.70a) */
#define DW_PCIE_VER_365A 0x3336352a
#define DW_PCIE_VER_460A 0x3436302a
@ -260,6 +262,21 @@
#define PCIE_RAS_DES_EVENT_COUNTER_DATA 0xc
/* PTM register definitions */
#define PTM_RES_REQ_CTRL 0x8
#define PTM_RES_CCONTEXT_VALID BIT(0)
#define PTM_REQ_AUTO_UPDATE_ENABLED BIT(0)
#define PTM_REQ_START_UPDATE BIT(1)
#define PTM_LOCAL_LSB 0x10
#define PTM_LOCAL_MSB 0x14
#define PTM_T1_T2_LSB 0x18
#define PTM_T1_T2_MSB 0x1c
#define PTM_T3_T4_LSB 0x28
#define PTM_T3_T4_MSB 0x2c
#define PTM_MASTER_LSB 0x38
#define PTM_MASTER_MSB 0x3c
/*
* The default address offset between dbi_base and atu_base. Root controller
* drivers are not required to initialize atu_base if the offset matches this
@ -412,6 +429,7 @@ struct dw_pcie_rp {
int msg_atu_index;
struct resource *msg_res;
bool use_linkup_irq;
struct pci_eq_presets presets;
};
struct dw_pcie_ep_ops {
@ -462,7 +480,7 @@ struct dw_pcie_ops {
size_t size, u32 val);
void (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
size_t size, u32 val);
int (*link_up)(struct dw_pcie *pcie);
bool (*link_up)(struct dw_pcie *pcie);
enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie);
int (*start_link)(struct dw_pcie *pcie);
void (*stop_link)(struct dw_pcie *pcie);
@ -503,6 +521,9 @@ struct dw_pcie {
struct gpio_desc *pe_rst;
bool suspended;
struct debugfs_info *debugfs;
enum dw_pcie_device_mode mode;
u16 ptm_vsec_offset;
struct pci_ptm_debugfs *ptm_debugfs;
/*
* If iATU input addresses are offset from CPU physical addresses,
@ -530,6 +551,7 @@ void dw_pcie_version_detect(struct dw_pcie *pci);
u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap);
u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap);
u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci);
u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci);
int dw_pcie_read(void __iomem *addr, int size, u32 *val);
int dw_pcie_write(void __iomem *addr, int size, u32 val);
@ -537,9 +559,10 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val);
u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size);
void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
int dw_pcie_link_up(struct dw_pcie *pci);
bool dw_pcie_link_up(struct dw_pcie *pci);
void dw_pcie_upconfig_setup(struct dw_pcie *pci);
int dw_pcie_wait_for_link(struct dw_pcie *pci);
int dw_pcie_link_get_max_link_width(struct dw_pcie *pci);
int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
const struct dw_pcie_ob_atu_cfg *atu);
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,
@ -871,10 +894,11 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
#endif
#ifdef CONFIG_PCIE_DW_DEBUGFS
void dwc_pcie_debugfs_init(struct dw_pcie *pci);
void dwc_pcie_debugfs_init(struct dw_pcie *pci, enum dw_pcie_device_mode mode);
void dwc_pcie_debugfs_deinit(struct dw_pcie *pci);
#else
static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci)
static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci,
enum dw_pcie_device_mode mode)
{
}
static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)

View file

@ -8,6 +8,7 @@
* Author: Simon Xue <xxm@rock-chips.com>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/irqchip/chained_irq.h>
@ -21,6 +22,7 @@
#include <linux/regmap.h>
#include <linux/reset.h>
#include "../../pci.h"
#include "pcie-designware.h"
/*
@ -33,26 +35,36 @@
#define to_rockchip_pcie(x) dev_get_drvdata((x)->dev)
#define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40)
#define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0)
#define PCIE_CLIENT_ENABLE_LTSSM HIWORD_UPDATE_BIT(0xc)
#define PCIE_CLIENT_DISABLE_LTSSM HIWORD_UPDATE(0x0c, 0x8)
#define PCIE_CLIENT_INTR_STATUS_MISC 0x10
#define PCIE_CLIENT_INTR_MASK_MISC 0x24
#define PCIE_SMLH_LINKUP BIT(16)
#define PCIE_RDLH_LINKUP BIT(17)
#define PCIE_LINKUP (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP)
#define PCIE_RDLH_LINK_UP_CHGED BIT(1)
#define PCIE_LINK_REQ_RST_NOT_INT BIT(2)
#define PCIE_L0S_ENTRY 0x11
#define PCIE_CLIENT_GENERAL_CONTROL 0x0
/* General Control Register */
#define PCIE_CLIENT_GENERAL_CON 0x0
#define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40)
#define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0)
#define PCIE_CLIENT_ENABLE_LTSSM HIWORD_UPDATE_BIT(0xc)
#define PCIE_CLIENT_DISABLE_LTSSM HIWORD_UPDATE(0x0c, 0x8)
/* Interrupt Status Register Related to Legacy Interrupt */
#define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8
/* Interrupt Status Register Related to Miscellaneous Operation */
#define PCIE_CLIENT_INTR_STATUS_MISC 0x10
#define PCIE_RDLH_LINK_UP_CHGED BIT(1)
#define PCIE_LINK_REQ_RST_NOT_INT BIT(2)
/* Interrupt Mask Register Related to Legacy Interrupt */
#define PCIE_CLIENT_INTR_MASK_LEGACY 0x1c
#define PCIE_CLIENT_GENERAL_DEBUG 0x104
/* Interrupt Mask Register Related to Miscellaneous Operation */
#define PCIE_CLIENT_INTR_MASK_MISC 0x24
/* Hot Reset Control Register */
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4)
/* LTSSM Status Register */
#define PCIE_CLIENT_LTSSM_STATUS 0x300
#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4)
#define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0)
#define PCIE_LINKUP 0x3
#define PCIE_LINKUP_MASK GENMASK(17, 16)
#define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0)
struct rockchip_pcie {
struct dw_pcie pci;
@ -163,25 +175,36 @@ static u32 rockchip_pcie_get_ltssm(struct rockchip_pcie *rockchip)
static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
{
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
PCIE_CLIENT_GENERAL_CONTROL);
PCIE_CLIENT_GENERAL_CON);
}
static void rockchip_pcie_disable_ltssm(struct rockchip_pcie *rockchip)
{
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DISABLE_LTSSM,
PCIE_CLIENT_GENERAL_CONTROL);
PCIE_CLIENT_GENERAL_CON);
}
static int rockchip_pcie_link_up(struct dw_pcie *pci)
static bool rockchip_pcie_link_up(struct dw_pcie *pci)
{
struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
u32 val = rockchip_pcie_get_ltssm(rockchip);
if ((val & PCIE_LINKUP) == PCIE_LINKUP &&
(val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY)
return 1;
return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
}
return 0;
static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
{
u32 cap, lnkcap;
/* Enable L0S capability for all SoCs */
cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
if (cap) {
lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP);
lnkcap |= PCI_EXP_LNKCAP_ASPM_L0S;
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writel_dbi(pci, cap + PCI_EXP_LNKCAP, lnkcap);
dw_pcie_dbi_ro_wr_dis(pci);
}
}
static int rockchip_pcie_start_link(struct dw_pcie *pci)
@ -202,7 +225,7 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
* We need more extra time as before, rather than setting just
* 100us as we don't know how long should the device need to reset.
*/
msleep(100);
msleep(PCIE_T_PVPERL_MS);
gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
return 0;
@ -233,6 +256,8 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
rockchip);
rockchip_pcie_enable_l0s(pci);
return 0;
}
@ -263,16 +288,14 @@ static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)
dev_err(dev, "failed to hide ATS capability\n");
}
static void rockchip_pcie_ep_pre_init(struct dw_pcie_ep *ep)
{
rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
}
static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
enum pci_barno bar;
rockchip_pcie_enable_l0s(pci);
rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
dw_pcie_ep_reset_bar(pci, bar);
};
@ -342,7 +365,6 @@ rockchip_pcie_get_features(struct dw_pcie_ep *ep)
static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = {
.init = rockchip_pcie_ep_init,
.pre_init = rockchip_pcie_ep_pre_init,
.raise_irq = rockchip_pcie_raise_irq,
.get_features = rockchip_pcie_get_features,
};
@ -410,8 +432,8 @@ static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
{
phy_exit(rockchip->phy);
phy_power_off(rockchip->phy);
phy_exit(rockchip->phy);
}
static const struct dw_pcie_ops dw_pcie_ops = {
@ -426,7 +448,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
struct dw_pcie *pci = &rockchip->pci;
struct dw_pcie_rp *pp = &pci->pp;
struct device *dev = pci->dev;
u32 reg, val;
u32 reg;
reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC);
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);
@ -435,8 +457,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip));
if (reg & PCIE_RDLH_LINK_UP_CHGED) {
val = rockchip_pcie_get_ltssm(rockchip);
if ((val & PCIE_LINKUP) == PCIE_LINKUP) {
if (rockchip_pcie_link_up(pci)) {
dev_dbg(dev, "Received Link up event. Starting enumeration!\n");
/* Rescan the bus to enumerate endpoint devices */
pci_lock_rescan_remove();
@ -453,7 +474,7 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)
struct rockchip_pcie *rockchip = arg;
struct dw_pcie *pci = &rockchip->pci;
struct device *dev = pci->dev;
u32 reg, val;
u32 reg;
reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC);
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);
@ -467,8 +488,7 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)
}
if (reg & PCIE_RDLH_LINK_UP_CHGED) {
val = rockchip_pcie_get_ltssm(rockchip);
if ((val & PCIE_LINKUP) == PCIE_LINKUP) {
if (rockchip_pcie_link_up(pci)) {
dev_dbg(dev, "link up\n");
dw_pcie_ep_linkup(&pci->ep);
}
@ -505,7 +525,7 @@ static int rockchip_pcie_configure_rc(struct platform_device *pdev,
rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
PCIE_CLIENT_GENERAL_CONTROL);
PCIE_CLIENT_GENERAL_CON);
pp = &rockchip->pci.pp;
pp->ops = &rockchip_pcie_host_ops;
@ -551,7 +571,7 @@ static int rockchip_pcie_configure_ep(struct platform_device *pdev,
rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE,
PCIE_CLIENT_GENERAL_CONTROL);
PCIE_CLIENT_GENERAL_CON);
rockchip->pci.ep.ops = &rockchip_pcie_ep_ops;
rockchip->pci.ep.page_size = SZ_64K;
@ -601,6 +621,10 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
rockchip->pci.ops = &dw_pcie_ops;
rockchip->data = data;
/* Default N_FTS value (210) is broken, override it to 255 */
rockchip->pci.n_fts[0] = 255; /* Gen1 */
rockchip->pci.n_fts[1] = 255; /* Gen2+ */
ret = rockchip_pcie_resource_get(pdev, rockchip);
if (ret)
return ret;

View file

@ -15,6 +15,7 @@
#include <linux/pci-acpi.h>
#include <linux/pci-ecam.h>
#include "../../pci.h"
#include "../pci-host-common.h"
#if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))

View file

@ -151,7 +151,7 @@ static struct pci_ops histb_pci_ops = {
.write = histb_pcie_wr_own_conf,
};
static int histb_pcie_link_up(struct dw_pcie *pci)
static bool histb_pcie_link_up(struct dw_pcie *pci)
{
struct histb_pcie *hipcie = to_histb_pcie(pci);
u32 regval;
@ -160,11 +160,8 @@ static int histb_pcie_link_up(struct dw_pcie *pci)
regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0);
status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4);
status &= PCIE_LTSSM_STATE_MASK;
if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) &&
(status == PCIE_LTSSM_STATE_ACTIVE))
return 1;
return 0;
return ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) &&
(status == PCIE_LTSSM_STATE_ACTIVE));
}
static int histb_pcie_start_link(struct dw_pcie *pci)

View file

@ -101,7 +101,7 @@ static void keembay_pcie_ltssm_set(struct keembay_pcie *pcie, bool enable)
writel(val, pcie->apb_base + PCIE_REGS_PCIE_APP_CNTRL);
}
static int keembay_pcie_link_up(struct dw_pcie *pci)
static bool keembay_pcie_link_up(struct dw_pcie *pci)
{
struct keembay_pcie *pcie = dev_get_drvdata(pci->dev);
u32 val;

View file

@ -586,16 +586,13 @@ static void kirin_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
kirin_pcie_sideband_dbi_w_mode(kirin_pcie, false);
}
static int kirin_pcie_link_up(struct dw_pcie *pci)
static bool kirin_pcie_link_up(struct dw_pcie *pci)
{
struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci);
u32 val;
regmap_read(kirin_pcie->apb, PCIE_APB_PHY_STATUS0, &val);
if ((val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE)
return 1;
return 0;
return (val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE;
}
static int kirin_pcie_start_link(struct dw_pcie *pci)

View file

@ -60,6 +60,7 @@
#define PARF_DEVICE_TYPE 0x1000
#define PARF_BDF_TO_SID_CFG 0x2c00
#define PARF_INT_ALL_5_MASK 0x2dcc
#define PARF_INT_ALL_3_MASK 0x2e18
/* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */
#define PARF_INT_ALL_LINK_DOWN BIT(1)
@ -132,6 +133,9 @@
/* PARF_INT_ALL_5_MASK fields */
#define PARF_INT_ALL_5_MHI_RAM_DATA_PARITY_ERR BIT(0)
/* PARF_INT_ALL_3_MASK fields */
#define PARF_INT_ALL_3_PTM_UPDATING BIT(4)
/* ELBI registers */
#define ELBI_SYS_STTS 0x08
#define ELBI_CS2_ENABLE 0xa4
@ -261,7 +265,7 @@ static void qcom_pcie_ep_configure_tcsr(struct qcom_pcie_ep *pcie_ep)
}
}
static int qcom_pcie_dw_link_up(struct dw_pcie *pci)
static bool qcom_pcie_dw_link_up(struct dw_pcie *pci)
{
struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci);
u32 reg;
@ -497,6 +501,10 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
writel_relaxed(val, pcie_ep->parf + PARF_INT_ALL_5_MASK);
}
val = readl_relaxed(pcie_ep->parf + PARF_INT_ALL_3_MASK);
val &= ~PARF_INT_ALL_3_PTM_UPDATING;
writel_relaxed(val, pcie_ep->parf + PARF_INT_ALL_3_MASK);
ret = dw_pcie_ep_init_registers(&pcie_ep->pci.ep);
if (ret) {
dev_err(dev, "Failed to complete initialization: %d\n", ret);

View file

@ -289,7 +289,7 @@ static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
{
/* Ensure that PERST has been asserted for at least 100 ms */
msleep(100);
msleep(PCIE_T_PVPERL_MS);
gpiod_set_value_cansleep(pcie->reset, 0);
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
}
@ -1221,12 +1221,12 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
return 0;
}
static int qcom_pcie_link_up(struct dw_pcie *pci)
static bool qcom_pcie_link_up(struct dw_pcie *pci)
{
u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
return !!(val & PCI_EXP_LNKSTA_DLLLA);
return val & PCI_EXP_LNKSTA_DLLLA;
}
static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
@ -1840,6 +1840,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
{ .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },

View file

@ -87,7 +87,7 @@ struct rcar_gen4_pcie {
#define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw)
/* Common */
static int rcar_gen4_pcie_link_up(struct dw_pcie *dw)
static bool rcar_gen4_pcie_link_up(struct dw_pcie *dw)
{
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
u32 val, mask;
@ -403,6 +403,7 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = {
.msix_capable = false,
.bar[BAR_1] = { .type = BAR_RESERVED, },
.bar[BAR_3] = { .type = BAR_RESERVED, },
.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256 },
.bar[BAR_5] = { .type = BAR_RESERVED, },
.align = SZ_1M,
};

View file

@ -110,15 +110,12 @@ static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pc
MSI_CTRL_INT, &app_reg->int_mask);
}
static int spear13xx_pcie_link_up(struct dw_pcie *pci)
static bool spear13xx_pcie_link_up(struct dw_pcie *pci)
{
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
return 1;
return 0;
return readl(&app_reg->app_status_1) & XMLH_LINK_UP;
}
static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp)

View file

@ -713,7 +713,16 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
static void init_debugfs(struct tegra_pcie_dw *pcie)
{
debugfs_create_devm_seqfile(pcie->dev, "aspm_state_cnt", pcie->debugfs,
struct device *dev = pcie->dev;
char *name;
name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
if (!name)
return;
pcie->debugfs = debugfs_create_dir(name, NULL);
debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,
aspm_state_cnt);
}
#else
@ -1027,12 +1036,12 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
return 0;
}
static int tegra_pcie_dw_link_up(struct dw_pcie *pci)
static bool tegra_pcie_dw_link_up(struct dw_pcie *pci)
{
struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
u32 val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
return !!(val & PCI_EXP_LNKSTA_DLLLA);
return val & PCI_EXP_LNKSTA_DLLLA;
}
static void tegra_pcie_dw_stop_link(struct dw_pcie *pci)
@ -1634,7 +1643,6 @@ static void tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie)
static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
{
struct device *dev = pcie->dev;
char *name;
int ret;
pm_runtime_enable(dev);
@ -1664,13 +1672,6 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
goto fail_host_init;
}
name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
if (!name) {
ret = -ENOMEM;
goto fail_host_init;
}
pcie->debugfs = debugfs_create_dir(name, NULL);
init_debugfs(pcie);
return ret;

View file

@ -135,7 +135,7 @@ static int uniphier_pcie_wait_rc(struct uniphier_pcie *pcie)
return 0;
}
static int uniphier_pcie_link_up(struct dw_pcie *pci)
static bool uniphier_pcie_link_up(struct dw_pcie *pci)
{
struct uniphier_pcie *pcie = to_uniphier_pcie(pci);
u32 val, mask;

View file

@ -121,13 +121,13 @@ static u32 visconti_mpu_readl(struct visconti_pcie *pcie, u32 reg)
return readl_relaxed(pcie->mpu_base + reg);
}
static int visconti_pcie_link_up(struct dw_pcie *pci)
static bool visconti_pcie_link_up(struct dw_pcie *pci)
{
struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);
void __iomem *addr = pcie->ulreg_base;
u32 val = readl_relaxed(addr + PCIE_UL_REG_V_PHY_ST_02);
return !!(val & PCIE_UL_S_L0);
return val & PCIE_UL_S_L0;
}
static int visconti_pcie_start_link(struct dw_pcie *pci)

View file

@ -53,18 +53,13 @@ static inline void ls_g4_pcie_pf_writel(struct ls_g4_pcie *pcie,
iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
}
static int ls_g4_pcie_link_up(struct mobiveil_pcie *pci)
static bool ls_g4_pcie_link_up(struct mobiveil_pcie *pci)
{
struct ls_g4_pcie *pcie = to_ls_g4_pcie(pci);
u32 state;
state = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG);
state = state & PF_DBG_LTSSM_MASK;
if (state == PF_DBG_LTSSM_L0)
return 1;
return 0;
return (state & PF_DBG_LTSSM_MASK) == PF_DBG_LTSSM_L0;
}
static void ls_g4_pcie_disable_interrupt(struct ls_g4_pcie *pcie)
@ -174,8 +169,7 @@ static int ls_g4_pcie_interrupt_init(struct mobiveil_pcie *mv_pci)
static void ls_g4_pcie_reset(struct work_struct *work)
{
struct delayed_work *dwork = container_of(work, struct delayed_work,
work);
struct delayed_work *dwork = to_delayed_work(work);
struct ls_g4_pcie *pcie = container_of(dwork, struct ls_g4_pcie, dwork);
struct mobiveil_pcie *mv_pci = &pcie->pci;
u16 ctrl;

View file

@ -160,7 +160,7 @@ struct mobiveil_root_port {
};
struct mobiveil_pab_ops {
int (*link_up)(struct mobiveil_pcie *pcie);
bool (*link_up)(struct mobiveil_pcie *pcie);
};
struct mobiveil_pcie {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Generic PCI host driver common code
* Common library for PCI host controller drivers
*
* Copyright (C) 2014 ARM Limited
*
@ -15,6 +15,8 @@
#include <linux/pci-ecam.h>
#include <linux/platform_device.h>
#include "pci-host-common.h"
static void gen_pci_unmap_cfg(void *ptr)
{
pci_ecam_free((struct pci_config_window *)ptr);
@ -49,23 +51,17 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
return cfg;
}
int pci_host_common_probe(struct platform_device *pdev)
int pci_host_common_init(struct platform_device *pdev,
const struct pci_ecam_ops *ops)
{
struct device *dev = &pdev->dev;
struct pci_host_bridge *bridge;
struct pci_config_window *cfg;
const struct pci_ecam_ops *ops;
ops = of_device_get_match_data(&pdev->dev);
if (!ops)
return -ENODEV;
bridge = devm_pci_alloc_host_bridge(dev, 0);
if (!bridge)
return -ENOMEM;
platform_set_drvdata(pdev, bridge);
of_pci_check_probe_only();
/* Parse and map our Configuration Space windows */
@ -73,6 +69,8 @@ int pci_host_common_probe(struct platform_device *pdev)
if (IS_ERR(cfg))
return PTR_ERR(cfg);
platform_set_drvdata(pdev, bridge);
bridge->sysdata = cfg;
bridge->ops = (struct pci_ops *)&ops->pci_ops;
bridge->enable_device = ops->enable_device;
@ -81,6 +79,18 @@ int pci_host_common_probe(struct platform_device *pdev)
return pci_host_probe(bridge);
}
EXPORT_SYMBOL_GPL(pci_host_common_init);
int pci_host_common_probe(struct platform_device *pdev)
{
const struct pci_ecam_ops *ops;
ops = of_device_get_match_data(&pdev->dev);
if (!ops)
return -ENODEV;
return pci_host_common_init(pdev, ops);
}
EXPORT_SYMBOL_GPL(pci_host_common_probe);
void pci_host_common_remove(struct platform_device *pdev)
@ -94,5 +104,5 @@ void pci_host_common_remove(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(pci_host_common_remove);
MODULE_DESCRIPTION("Generic PCI host common driver");
MODULE_DESCRIPTION("Common library for PCI host controller drivers");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Common library for PCI host controller drivers
*
* Copyright (C) 2014 ARM Limited
*
* Author: Will Deacon <will.deacon@arm.com>
*/
#ifndef _PCI_HOST_COMMON_H
#define _PCI_HOST_COMMON_H
struct pci_ecam_ops;
int pci_host_common_probe(struct platform_device *pdev);
int pci_host_common_init(struct platform_device *pdev,
const struct pci_ecam_ops *ops);
void pci_host_common_remove(struct platform_device *pdev);
#endif

Some files were not shown because too many files have changed in this diff Show more