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:
		
						commit
						3719a04a80
					
				
					 148 changed files with 3401 additions and 2220 deletions
				
			
		
							
								
								
									
										3
									
								
								.mailmap
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								.mailmap
									
									
									
									
									
								
							|  | @ -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.k@gmail.com> | ||||||
| Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com> | Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com> | ||||||
| Krzysztof Kozlowski <krzk@kernel.org> <krzysztof.kozlowski@canonical.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> | Kshitiz Godara <quic_kgodara@quicinc.com> <kgodara@codeaurora.org> | ||||||
| Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||||||
| Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org> | 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> | Malathi Gottam <quic_mgottam@quicinc.com> <mgottam@codeaurora.org> | ||||||
| Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org> | Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org> | ||||||
| Manivannan Sadhasivam <mani@kernel.org> <manivannanece23@gmail.com> | 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> | Manoj Basapathi <quic_manojbm@quicinc.com> <manojbm@codeaurora.org> | ||||||
| Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com> | Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com> | ||||||
| Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com> | Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com> | ||||||
|  |  | ||||||
							
								
								
									
										70
									
								
								Documentation/ABI/testing/debugfs-pcie-ptm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								Documentation/ABI/testing/debugfs-pcie-ptm
									
									
									
									
									
										Normal 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 | ||||||
|  | @ -117,3 +117,47 @@ Date:		July 2018 | ||||||
| KernelVersion:	4.19.0 | KernelVersion:	4.19.0 | ||||||
| Contact:	linux-pci@vger.kernel.org, rajatja@google.com | Contact:	linux-pci@vger.kernel.org, rajatja@google.com | ||||||
| Description:	Total number of ERR_NONFATAL messages reported to rootport. | 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). | ||||||
							
								
								
									
										10
									
								
								Documentation/PCI/controller/index.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Documentation/PCI/controller/index.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | .. SPDX-License-Identifier: GPL-2.0 | ||||||
|  | 
 | ||||||
|  | =========================================== | ||||||
|  | PCI Native Host Bridge and Endpoint Drivers | ||||||
|  | =========================================== | ||||||
|  | 
 | ||||||
|  | .. toctree:: | ||||||
|  |    :maxdepth: 2 | ||||||
|  | 
 | ||||||
|  |    rcar-pcie-firmware | ||||||
							
								
								
									
										32
									
								
								Documentation/PCI/controller/rcar-pcie-firmware.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Documentation/PCI/controller/rcar-pcie-firmware.rst
									
									
									
									
									
										Normal 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. | ||||||
|  | @ -8,6 +8,6 @@ PCI NVMe Function | ||||||
| 
 | 
 | ||||||
| The PCI NVMe endpoint function implements a PCI NVMe controller using the NVMe | 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 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. | See Documentation/nvme/nvme-pci-endpoint-target.rst for more details. | ||||||
|  |  | ||||||
|  | @ -17,5 +17,6 @@ PCI Bus Subsystem | ||||||
|    pci-error-recovery |    pci-error-recovery | ||||||
|    pcieaer-howto |    pcieaer-howto | ||||||
|    endpoint/index |    endpoint/index | ||||||
|  |    controller/index | ||||||
|    boot-interrupts |    boot-interrupts | ||||||
|    tph |    tph | ||||||
|  |  | ||||||
|  | @ -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 | the error message to the Root Port. Please refer to PCIe specs for other | ||||||
| fields. | 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 | AER Statistics / Counters | ||||||
| ------------------------- | ------------------------- | ||||||
| 
 | 
 | ||||||
| When PCIe AER errors are captured, the counters / statistics are also exposed | When PCIe AER errors are captured, the counters / statistics are also exposed | ||||||
| in the form of sysfs attributes which are documented at | 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 | Developer Guide | ||||||
| =============== | =============== | ||||||
|  |  | ||||||
|  | @ -17,6 +17,10 @@ description: | | ||||||
|   implements its root ports.  But the ATU found on most DesignWare |   implements its root ports.  But the ATU found on most DesignWare | ||||||
|   PCIe host bridges is absent. |   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 |   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 |   used to take the PCI devices on those ports out of reset.  Therefore | ||||||
|   the standard "reset-gpios" and "max-link-speed" properties appear on |   the standard "reset-gpios" and "max-link-speed" properties appear on | ||||||
|  | @ -30,16 +34,18 @@ description: | | ||||||
| 
 | 
 | ||||||
| properties: | properties: | ||||||
|   compatible: |   compatible: | ||||||
|     items: |     oneOf: | ||||||
|  |       - items: | ||||||
|           - enum: |           - enum: | ||||||
|               - apple,t8103-pcie |               - apple,t8103-pcie | ||||||
|               - apple,t8112-pcie |               - apple,t8112-pcie | ||||||
|               - apple,t6000-pcie |               - apple,t6000-pcie | ||||||
|           - const: apple,pcie |           - const: apple,pcie | ||||||
|  |       - const: apple,t6020-pcie | ||||||
| 
 | 
 | ||||||
|   reg: |   reg: | ||||||
|     minItems: 3 |     minItems: 3 | ||||||
|     maxItems: 6 |     maxItems: 10 | ||||||
| 
 | 
 | ||||||
|   reg-names: |   reg-names: | ||||||
|     minItems: 3 |     minItems: 3 | ||||||
|  | @ -50,6 +56,10 @@ properties: | ||||||
|       - const: port1 |       - const: port1 | ||||||
|       - const: port2 |       - const: port2 | ||||||
|       - const: port3 |       - const: port3 | ||||||
|  |       - const: phy0 | ||||||
|  |       - const: phy1 | ||||||
|  |       - const: phy2 | ||||||
|  |       - const: phy3 | ||||||
| 
 | 
 | ||||||
|   ranges: |   ranges: | ||||||
|     minItems: 2 |     minItems: 2 | ||||||
|  | @ -98,6 +108,15 @@ allOf: | ||||||
|           maxItems: 5 |           maxItems: 5 | ||||||
|         interrupts: |         interrupts: | ||||||
|           maxItems: 3 |           maxItems: 3 | ||||||
|  |   - if: | ||||||
|  |       properties: | ||||||
|  |         compatible: | ||||||
|  |           contains: | ||||||
|  |             const: apple,t6020-pcie | ||||||
|  |     then: | ||||||
|  |       properties: | ||||||
|  |         reg-names: | ||||||
|  |           minItems: 10 | ||||||
| 
 | 
 | ||||||
| examples: | examples: | ||||||
|   - | |   - | | ||||||
|  |  | ||||||
|  | @ -224,8 +224,7 @@ examples: | ||||||
| 
 | 
 | ||||||
|                 /* PCIe endpoint */ |                 /* PCIe endpoint */ | ||||||
|                 pci-ep@0,0 { |                 pci-ep@0,0 { | ||||||
|                                     assigned-addresses = |                     assigned-addresses = <0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>; | ||||||
|                                         <0x82010000 0x0 0xf8000000 0x6 0x00000000 0x0 0x2000>; |  | ||||||
|                     reg = <0x0 0x0 0x0 0x0 0x0>; |                     reg = <0x0 0x0 0x0 0x0 0x0>; | ||||||
|                     compatible = "pci14e4,1688"; |                     compatible = "pci14e4,1688"; | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
							
								
								
									
										100
									
								
								Documentation/devicetree/bindings/pci/marvell,armada8k-pcie.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Documentation/devicetree/bindings/pci/marvell,armada8k-pcie.yaml
									
									
									
									
									
										Normal 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>; | ||||||
|  |     }; | ||||||
|  | ... | ||||||
							
								
								
									
										277
									
								
								Documentation/devicetree/bindings/pci/marvell,kirkwood-pcie.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								Documentation/devicetree/bindings/pci/marvell,kirkwood-pcie.yaml
									
									
									
									
									
										Normal 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>; | ||||||
|  |             }; | ||||||
|  |         }; | ||||||
|  |     }; | ||||||
|  | ... | ||||||
|  | @ -50,7 +50,7 @@ properties: | ||||||
|     items: |     items: | ||||||
|       pattern: '^fic[0-3]$' |       pattern: '^fic[0-3]$' | ||||||
| 
 | 
 | ||||||
|   dma-coherent: true |   dma-noncoherent: true | ||||||
| 
 | 
 | ||||||
|   ranges: |   ranges: | ||||||
|     minItems: 1 |     minItems: 1 | ||||||
|  |  | ||||||
|  | @ -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>; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  | @ -74,7 +74,7 @@ properties: | ||||||
| 
 | 
 | ||||||
|   reset-gpios: |   reset-gpios: | ||||||
|     description: Must contain a phandle to a GPIO controller followed by GPIO |     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: |   phys: | ||||||
|     minItems: 1 |     minItems: 1 | ||||||
|  |  | ||||||
|  | @ -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>; |  | ||||||
| 	}; |  | ||||||
|  | @ -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>; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  | @ -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>; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  | @ -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; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  | @ -45,9 +45,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -57,6 +58,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -129,7 +131,8 @@ examples: | ||||||
|                          <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 374 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", |             interrupt-names = "msi0", | ||||||
|                               "msi1", |                               "msi1", | ||||||
|                               "msi2", |                               "msi2", | ||||||
|  | @ -137,7 +140,8 @@ examples: | ||||||
|                               "msi4", |                               "msi4", | ||||||
|                               "msi5", |                               "msi5", | ||||||
|                               "msi6", |                               "msi6", | ||||||
|                               "msi7"; |                               "msi7", | ||||||
|  |                               "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>, |             interrupt-map = <0 0 0 1 &intc GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|  |  | ||||||
|  | @ -54,9 +54,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -66,6 +67,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -149,9 +151,10 @@ examples: | ||||||
|                          <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 374 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", |             interrupt-names = "msi0", "msi1", "msi2", "msi3", | ||||||
|                               "msi4", "msi5", "msi6", "msi7"; |                               "msi4", "msi5", "msi6", "msi7", "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>, |             interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|  |  | ||||||
|  | @ -49,9 +49,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -61,6 +62,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -136,7 +138,8 @@ examples: | ||||||
|                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 147 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", |             interrupt-names = "msi0", | ||||||
|                           "msi1", |                           "msi1", | ||||||
|                           "msi2", |                           "msi2", | ||||||
|  | @ -144,7 +147,8 @@ examples: | ||||||
|                           "msi4", |                           "msi4", | ||||||
|                           "msi5", |                           "msi5", | ||||||
|                           "msi6", |                           "msi6", | ||||||
|                           "msi7"; |                           "msi7", | ||||||
|  |                           "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ |             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||||||
|  |  | ||||||
|  | @ -49,9 +49,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -61,6 +62,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -128,9 +130,10 @@ examples: | ||||||
|                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 147 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", |             interrupt-names = "msi0", "msi1", "msi2", "msi3", | ||||||
|                               "msi4", "msi5", "msi6", "msi7"; |                               "msi4", "msi5", "msi6", "msi7", "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ |             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||||||
|  |  | ||||||
|  | @ -61,9 +61,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -73,6 +74,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -143,9 +145,10 @@ examples: | ||||||
|                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 147 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", |             interrupt-names = "msi0", "msi1", "msi2", "msi3", | ||||||
|                               "msi4", "msi5", "msi6", "msi7"; |                               "msi4", "msi5", "msi6", "msi7", "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ |             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||||||
|  |  | ||||||
|  | @ -51,9 +51,10 @@ properties: | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|     minItems: 8 |     minItems: 8 | ||||||
|     maxItems: 8 |     maxItems: 9 | ||||||
| 
 | 
 | ||||||
|   interrupt-names: |   interrupt-names: | ||||||
|  |     minItems: 8 | ||||||
|     items: |     items: | ||||||
|       - const: msi0 |       - const: msi0 | ||||||
|       - const: msi1 |       - const: msi1 | ||||||
|  | @ -63,6 +64,7 @@ properties: | ||||||
|       - const: msi5 |       - const: msi5 | ||||||
|       - const: msi6 |       - const: msi6 | ||||||
|       - const: msi7 |       - const: msi7 | ||||||
|  |       - const: global | ||||||
| 
 | 
 | ||||||
|   resets: |   resets: | ||||||
|     maxItems: 1 |     maxItems: 1 | ||||||
|  | @ -132,9 +134,10 @@ examples: | ||||||
|                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, |                          <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, | ||||||
|                          <GIC_SPI 147 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", |             interrupt-names = "msi0", "msi1", "msi2", "msi3", | ||||||
|                               "msi4", "msi5", "msi6", "msi7"; |                               "msi4", "msi5", "msi6", "msi7", "global"; | ||||||
|             #interrupt-cells = <1>; |             #interrupt-cells = <1>; | ||||||
|             interrupt-map-mask = <0 0 0 0x7>; |             interrupt-map-mask = <0 0 0 0x7>; | ||||||
|             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ |             interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ properties: | ||||||
|           - qcom,pcie-apq8064 |           - qcom,pcie-apq8064 | ||||||
|           - qcom,pcie-apq8084 |           - qcom,pcie-apq8084 | ||||||
|           - qcom,pcie-ipq4019 |           - qcom,pcie-ipq4019 | ||||||
|  |           - qcom,pcie-ipq5018 | ||||||
|           - qcom,pcie-ipq6018 |           - qcom,pcie-ipq6018 | ||||||
|           - qcom,pcie-ipq8064 |           - qcom,pcie-ipq8064 | ||||||
|           - qcom,pcie-ipq8064-v2 |           - qcom,pcie-ipq8064-v2 | ||||||
|  | @ -168,6 +169,7 @@ allOf: | ||||||
|         compatible: |         compatible: | ||||||
|           contains: |           contains: | ||||||
|             enum: |             enum: | ||||||
|  |               - qcom,pcie-ipq5018 | ||||||
|               - qcom,pcie-ipq6018 |               - qcom,pcie-ipq6018 | ||||||
|               - qcom,pcie-ipq8074-gen3 |               - qcom,pcie-ipq8074-gen3 | ||||||
|               - qcom,pcie-ipq9574 |               - qcom,pcie-ipq9574 | ||||||
|  | @ -175,14 +177,16 @@ allOf: | ||||||
|       properties: |       properties: | ||||||
|         reg: |         reg: | ||||||
|           minItems: 5 |           minItems: 5 | ||||||
|           maxItems: 5 |           maxItems: 6 | ||||||
|         reg-names: |         reg-names: | ||||||
|  |           minItems: 5 | ||||||
|           items: |           items: | ||||||
|             - const: dbi # DesignWare PCIe registers |             - const: dbi # DesignWare PCIe registers | ||||||
|             - const: elbi # External local bus interface registers |             - const: elbi # External local bus interface registers | ||||||
|             - const: atu # ATU address space |             - const: atu # ATU address space | ||||||
|             - const: parf # Qualcomm specific registers |             - const: parf # Qualcomm specific registers | ||||||
|             - const: config # PCIe configuration space |             - const: config # PCIe configuration space | ||||||
|  |             - const: mhi # MHI registers | ||||||
| 
 | 
 | ||||||
|   - if: |   - if: | ||||||
|       properties: |       properties: | ||||||
|  | @ -322,6 +326,53 @@ allOf: | ||||||
|             - const: ahb # AHB reset |             - const: ahb # AHB reset | ||||||
|             - const: phy_ahb # PHY 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: |   - if: | ||||||
|       properties: |       properties: | ||||||
|         compatible: |         compatible: | ||||||
|  | @ -562,6 +613,7 @@ allOf: | ||||||
|               enum: |               enum: | ||||||
|                 - qcom,pcie-apq8064 |                 - qcom,pcie-apq8064 | ||||||
|                 - qcom,pcie-ipq4019 |                 - qcom,pcie-ipq4019 | ||||||
|  |                 - qcom,pcie-ipq5018 | ||||||
|                 - qcom,pcie-ipq8064 |                 - qcom,pcie-ipq8064 | ||||||
|                 - qcom,pcie-ipq8064v2 |                 - qcom,pcie-ipq8064v2 | ||||||
|                 - qcom,pcie-ipq8074 |                 - qcom,pcie-ipq8074 | ||||||
|  | @ -589,7 +641,11 @@ allOf: | ||||||
|         compatible: |         compatible: | ||||||
|           contains: |           contains: | ||||||
|             enum: |             enum: | ||||||
|  |               - qcom,pcie-ipq6018 | ||||||
|  |               - qcom,pcie-ipq8074 | ||||||
|  |               - qcom,pcie-ipq8074-gen3 | ||||||
|               - qcom,pcie-msm8996 |               - qcom,pcie-msm8996 | ||||||
|  |               - qcom,pcie-msm8998 | ||||||
|               - qcom,pcie-sdm845 |               - qcom,pcie-sdm845 | ||||||
|     then: |     then: | ||||||
|       oneOf: |       oneOf: | ||||||
|  | @ -602,8 +658,9 @@ allOf: | ||||||
|         - properties: |         - properties: | ||||||
|             interrupts: |             interrupts: | ||||||
|               minItems: 8 |               minItems: 8 | ||||||
|               maxItems: 8 |               maxItems: 9 | ||||||
|             interrupt-names: |             interrupt-names: | ||||||
|  |               minItems: 8 | ||||||
|               items: |               items: | ||||||
|                 - const: msi0 |                 - const: msi0 | ||||||
|                 - const: msi1 |                 - const: msi1 | ||||||
|  | @ -613,6 +670,7 @@ allOf: | ||||||
|                 - const: msi5 |                 - const: msi5 | ||||||
|                 - const: msi6 |                 - const: msi6 | ||||||
|                 - const: msi7 |                 - const: msi7 | ||||||
|  |                 - const: global | ||||||
| 
 | 
 | ||||||
|   - if: |   - if: | ||||||
|       properties: |       properties: | ||||||
|  | @ -622,11 +680,8 @@ allOf: | ||||||
|               - qcom,pcie-apq8064 |               - qcom,pcie-apq8064 | ||||||
|               - qcom,pcie-apq8084 |               - qcom,pcie-apq8084 | ||||||
|               - qcom,pcie-ipq4019 |               - qcom,pcie-ipq4019 | ||||||
|               - qcom,pcie-ipq6018 |  | ||||||
|               - qcom,pcie-ipq8064 |               - qcom,pcie-ipq8064 | ||||||
|               - qcom,pcie-ipq8064-v2 |               - qcom,pcie-ipq8064-v2 | ||||||
|               - qcom,pcie-ipq8074 |  | ||||||
|               - qcom,pcie-ipq8074-gen3 |  | ||||||
|               - qcom,pcie-qcs404 |               - qcom,pcie-qcs404 | ||||||
|     then: |     then: | ||||||
|       properties: |       properties: | ||||||
|  |  | ||||||
|  | @ -65,7 +65,11 @@ properties: | ||||||
|           tx_cpl_timeout, cor_err_sent, nf_err_sent, f_err_sent, cor_err_rx, |           tx_cpl_timeout, cor_err_sent, nf_err_sent, f_err_sent, cor_err_rx, | ||||||
|           nf_err_rx, f_err_rx, radm_qoverflow |           nf_err_rx, f_err_rx, radm_qoverflow | ||||||
|       - description: |       - 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: |       - description: | ||||||
|           eDMA write channel 1 interrupt |           eDMA write channel 1 interrupt | ||||||
|       - description: |       - description: | ||||||
|  | @ -81,7 +85,9 @@ properties: | ||||||
|       - const: msg |       - const: msg | ||||||
|       - const: legacy |       - const: legacy | ||||||
|       - const: err |       - const: err | ||||||
|       - const: dma0 |       - enum: | ||||||
|  |           - msi | ||||||
|  |           - dma0 | ||||||
|       - const: dma1 |       - const: dma1 | ||||||
|       - const: dma2 |       - const: dma2 | ||||||
|       - const: dma3 |       - const: dma3 | ||||||
|  |  | ||||||
|  | @ -16,16 +16,14 @@ description: |+ | ||||||
|   PCIe IP and thus inherits all the common properties defined in |   PCIe IP and thus inherits all the common properties defined in | ||||||
|   snps,dw-pcie.yaml. |   snps,dw-pcie.yaml. | ||||||
| 
 | 
 | ||||||
| allOf: |  | ||||||
|   - $ref: /schemas/pci/snps,dw-pcie.yaml# |  | ||||||
|   - $ref: /schemas/pci/rockchip-dw-pcie-common.yaml# |  | ||||||
| 
 |  | ||||||
| properties: | properties: | ||||||
|   compatible: |   compatible: | ||||||
|     oneOf: |     oneOf: | ||||||
|       - const: rockchip,rk3568-pcie |       - const: rockchip,rk3568-pcie | ||||||
|       - items: |       - items: | ||||||
|           - enum: |           - enum: | ||||||
|  |               - rockchip,rk3562-pcie | ||||||
|  |               - rockchip,rk3576-pcie | ||||||
|               - rockchip,rk3588-pcie |               - rockchip,rk3588-pcie | ||||||
|           - const: rockchip,rk3568-pcie |           - const: rockchip,rk3568-pcie | ||||||
| 
 | 
 | ||||||
|  | @ -71,9 +69,59 @@ properties: | ||||||
| 
 | 
 | ||||||
|   vpcie3v3-supply: true |   vpcie3v3-supply: true | ||||||
| 
 | 
 | ||||||
|  | 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: |       required: | ||||||
|         - msi-map |         - 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 | unevaluatedProperties: false | ||||||
| 
 | 
 | ||||||
| examples: | examples: | ||||||
|  |  | ||||||
|  | @ -81,10 +81,10 @@ unevaluatedProperties: false | ||||||
| 
 | 
 | ||||||
| examples: | examples: | ||||||
|   - | |   - | | ||||||
|  |     #include <dt-bindings/clock/sifive-fu740-prci.h> | ||||||
|     bus { |     bus { | ||||||
|         #address-cells = <2>; |         #address-cells = <2>; | ||||||
|         #size-cells = <2>; |         #size-cells = <2>; | ||||||
|         #include <dt-bindings/clock/sifive-fu740-prci.h> |  | ||||||
| 
 | 
 | ||||||
|         pcie@e00000000 { |         pcie@e00000000 { | ||||||
|             compatible = "sifive,fu740-pcie"; |             compatible = "sifive,fu740-pcie"; | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ properties: | ||||||
|             above for new bindings. |             above for new bindings. | ||||||
|           oneOf: |           oneOf: | ||||||
|             - description: See native 'dbi' clock for details |             - 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 |             - description: See native 'mstr/slv' clock for details | ||||||
|               enum: [ pcie_bus, pcie_inbound_axi, pcie_aclk, aclk_mst, aclk_slv ] |               enum: [ pcie_bus, pcie_inbound_axi, pcie_aclk, aclk_mst, aclk_slv ] | ||||||
|             - description: See native 'pipe' clock for details |             - description: See native 'pipe' clock for details | ||||||
|  | @ -201,6 +201,7 @@ properties: | ||||||
|           oneOf: |           oneOf: | ||||||
|             - pattern: '^pcie(-?phy[0-9]*)?$' |             - pattern: '^pcie(-?phy[0-9]*)?$' | ||||||
|             - pattern: '^p2u-[0-7]$' |             - pattern: '^p2u-[0-7]$' | ||||||
|  |             - pattern: '^cp[01]-pcie[0-2]-x[124](-lane[0-3])?-phy$'  # marvell,armada8k-pcie | ||||||
| 
 | 
 | ||||||
|   reset-gpio: |   reset-gpio: | ||||||
|     deprecated: true |     deprecated: true | ||||||
|  |  | ||||||
|  | @ -105,6 +105,8 @@ properties: | ||||||
|             Vendor-specific CSR names. Consider using the generic names above |             Vendor-specific CSR names. Consider using the generic names above | ||||||
|             for new bindings. |             for new bindings. | ||||||
|           oneOf: |           oneOf: | ||||||
|  |             - description: See native 'dbi' CSR region for details. | ||||||
|  |               enum: [ ctrl ] | ||||||
|             - description: See native 'elbi/app' CSR region for details. |             - description: See native 'elbi/app' CSR region for details. | ||||||
|               enum: [ apb, mgmt, link, ulreg, appl ] |               enum: [ apb, mgmt, link, ulreg, appl ] | ||||||
|             - description: See native 'atu' CSR region for details. |             - description: See native 'atu' CSR region for details. | ||||||
|  | @ -117,7 +119,7 @@ properties: | ||||||
|               const: slcr |               const: slcr | ||||||
|     allOf: |     allOf: | ||||||
|       - contains: |       - contains: | ||||||
|           const: dbi |           enum: [ dbi, ctrl ] | ||||||
|       - contains: |       - contains: | ||||||
|           const: config |           const: config | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										100
									
								
								Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
									
									
									
									
									
										Normal 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 */ | ||||||
|  |     }; | ||||||
|  | ... | ||||||
|  | @ -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 */ |  | ||||||
| 	>; |  | ||||||
| }; |  | ||||||
|  | @ -76,11 +76,10 @@ unevaluatedProperties: false | ||||||
| 
 | 
 | ||||||
| examples: | examples: | ||||||
|   - | |   - | | ||||||
| 
 |  | ||||||
|     versal { |     versal { | ||||||
|         #address-cells = <2>; |         #address-cells = <2>; | ||||||
|         #size-cells = <2>; |         #size-cells = <2>; | ||||||
|                cpm_pcie: pcie@fca10000 { |         pcie@fca10000 { | ||||||
|             compatible = "xlnx,versal-cpm-host-1.00"; |             compatible = "xlnx,versal-cpm-host-1.00"; | ||||||
|             device_type = "pci"; |             device_type = "pci"; | ||||||
|             #address-cells = <3>; |             #address-cells = <3>; | ||||||
|  | @ -107,7 +106,7 @@ examples: | ||||||
|             }; |             }; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|                cpm5_pcie: pcie@fcdd0000 { |         pcie@fcdd0000 { | ||||||
|             compatible = "xlnx,versal-cpm5-host"; |             compatible = "xlnx,versal-cpm5-host"; | ||||||
|             device_type = "pci"; |             device_type = "pci"; | ||||||
|             #address-cells = <3>; |             #address-cells = <3>; | ||||||
|  | @ -135,5 +134,4 @@ examples: | ||||||
|                 interrupt-controller; |                 interrupt-controller; | ||||||
|             }; |             }; | ||||||
|         }; |         }; | ||||||
| 
 |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -391,12 +391,11 @@ PCI | ||||||
|   devm_pci_remap_cfgspace()	: ioremap PCI configuration space |   devm_pci_remap_cfgspace()	: ioremap PCI configuration space | ||||||
|   devm_pci_remap_cfg_resource()	: ioremap PCI configuration space resource |   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()			: do iomap() on a single BAR | ||||||
|   pcim_iomap_regions()		: do request_region() and iomap() on multiple BARs |   pcim_iomap_regions()		: do request_region() and iomap() on multiple BARs | ||||||
|   pcim_iomap_table()		: array of mapped addresses indexed by BAR |   pcim_iomap_table()		: array of mapped addresses indexed by BAR | ||||||
|   pcim_iounmap()		: do iounmap() on a single 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_pin_device()		: keep PCI device enabled after release | ||||||
|   pcim_set_mwi()		: enable Memory-Write-Invalidate PCI transaction |   pcim_set_mwi()		: enable Memory-Write-Invalidate PCI transaction | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								MAINTAINERS
									
									
									
									
									
								
							|  | @ -2147,7 +2147,7 @@ F:	arch/arm/plat-*/ | ||||||
| 
 | 
 | ||||||
| ARM/ACTIONS SEMI ARCHITECTURE | ARM/ACTIONS SEMI ARCHITECTURE | ||||||
| M:	Andreas Färber <afaerber@suse.de> | 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-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||||||
| L:	linux-actions@lists.infradead.org (moderated for non-subscribers) | L:	linux-actions@lists.infradead.org (moderated for non-subscribers) | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -2400,7 +2400,7 @@ F:	arch/arm/boot/dts/intel/axm/ | ||||||
| F:	arch/arm/mach-axxia/ | F:	arch/arm/mach-axxia/ | ||||||
| 
 | 
 | ||||||
| ARM/BITMAIN ARCHITECTURE | 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) | L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	Documentation/devicetree/bindings/arm/bitmain.yaml | F:	Documentation/devicetree/bindings/arm/bitmain.yaml | ||||||
|  | @ -3069,7 +3069,7 @@ F:	include/linux/soc/qcom/ | ||||||
| F:	include/soc/qcom/ | F:	include/soc/qcom/ | ||||||
| 
 | 
 | ||||||
| ARM/RDA MICRO ARCHITECTURE | 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-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||||||
| L:	linux-unisoc@lists.infradead.org (moderated for non-subscribers) | L:	linux-unisoc@lists.infradead.org (moderated for non-subscribers) | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -3776,7 +3776,7 @@ F:	Documentation/admin-guide/aoe/ | ||||||
| F:	drivers/block/aoe/ | F:	drivers/block/aoe/ | ||||||
| 
 | 
 | ||||||
| ATC260X PMIC MFD DRIVER | ATC260X PMIC MFD DRIVER | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| M:	Cristian Ciocaltea <cristian.ciocaltea@gmail.com> | M:	Cristian Ciocaltea <cristian.ciocaltea@gmail.com> | ||||||
| L:	linux-actions@lists.infradead.org | L:	linux-actions@lists.infradead.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -6806,7 +6806,7 @@ S:	Orphan | ||||||
| F:	drivers/mtd/nand/raw/denali* | F:	drivers/mtd/nand/raw/denali* | ||||||
| 
 | 
 | ||||||
| DESIGNWARE EDMA CORE IP DRIVER | DESIGNWARE EDMA CORE IP DRIVER | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| L:	dmaengine@vger.kernel.org | L:	dmaengine@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	drivers/dma/dw-edma/ | F:	drivers/dma/dw-edma/ | ||||||
|  | @ -8652,7 +8652,7 @@ S:	Maintained | ||||||
| F:	drivers/edac/pnd2_edac.[ch] | F:	drivers/edac/pnd2_edac.[ch] | ||||||
| 
 | 
 | ||||||
| EDAC-QCOM | EDAC-QCOM | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| L:	linux-edac@vger.kernel.org | L:	linux-edac@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -12270,7 +12270,7 @@ M:	Andy Shevchenko <andy@kernel.org> | ||||||
| L:	linux-kernel@vger.kernel.org | L:	linux-kernel@vger.kernel.org | ||||||
| S:	Supported | S:	Supported | ||||||
| F:	arch/x86/include/asm/intel-mid.h | 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:	arch/x86/platform/intel-mid/ | ||||||
| F:	drivers/dma/hsu/ | F:	drivers/dma/hsu/ | ||||||
| F:	drivers/extcon/extcon-intel-mrfld.c | F:	drivers/extcon/extcon-intel-mrfld.c | ||||||
|  | @ -14859,7 +14859,7 @@ F:	drivers/hid/hid-mcp2221.c | ||||||
| 
 | 
 | ||||||
| MCP251XFD SPI-CAN NETWORK DRIVER | MCP251XFD SPI-CAN NETWORK DRIVER | ||||||
| M:	Marc Kleine-Budde <mkl@pengutronix.de> | 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> | R:	Thomas Kopp <thomas.kopp@microchip.com> | ||||||
| L:	linux-can@vger.kernel.org | L:	linux-can@vger.kernel.org | ||||||
| S:	Maintained | 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.* | F:	arch/arm64/boot/dts/marvell/armada-3720-uDPU.* | ||||||
| 
 | 
 | ||||||
| MHI BUS | MHI BUS | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| L:	mhi@lists.linux.dev | L:	mhi@lists.linux.dev | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -18837,7 +18837,7 @@ M:	Thomas Petazzoni <thomas.petazzoni@bootlin.com> | ||||||
| L:	linux-pci@vger.kernel.org | L:	linux-pci@vger.kernel.org | ||||||
| L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||||||
| S:	Maintained | 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 | F:	drivers/pci/controller/dwc/pcie-armada8k.c | ||||||
| 
 | 
 | ||||||
| PCI DRIVER FOR CADENCE PCIE IP | 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-pci@vger.kernel.org | ||||||
| L:	linux-renesas-soc@vger.kernel.org | L:	linux-renesas-soc@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | F:	Documentation/PCI/controller/rcar-pcie-firmware.rst | ||||||
| F:	Documentation/devicetree/bindings/pci/*rcar* | F:	Documentation/devicetree/bindings/pci/*rcar* | ||||||
| F:	drivers/pci/controller/*rcar* | F:	drivers/pci/controller/*rcar* | ||||||
| F:	drivers/pci/controller/dwc/*rcar* | F:	drivers/pci/controller/dwc/*rcar* | ||||||
|  | @ -18971,7 +18972,7 @@ F:	drivers/pci/controller/dwc/pci-exynos.c | ||||||
| 
 | 
 | ||||||
| PCI DRIVER FOR SYNOPSYS DESIGNWARE | PCI DRIVER FOR SYNOPSYS DESIGNWARE | ||||||
| M:	Jingoo Han <jingoohan1@gmail.com> | 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 | L:	linux-pci@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml | 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> | M:	Linus Walleij <linus.walleij@linaro.org> | ||||||
| L:	linux-pci@vger.kernel.org | L:	linux-pci@vger.kernel.org | ||||||
| S:	Maintained | 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 | F:	drivers/pci/controller/pci-v3-semi.c | ||||||
| 
 | 
 | ||||||
| PCI DRIVER FOR XILINX VERSAL CPM | 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 | F:	drivers/pci/controller/pcie-xilinx-cpm.c | ||||||
| 
 | 
 | ||||||
| PCI ENDPOINT SUBSYSTEM | PCI ENDPOINT SUBSYSTEM | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| M:	Krzysztof Wilczyński <kw@linux.com> | M:	Krzysztof Wilczyński <kwilczynski@kernel.org> | ||||||
| R:	Kishon Vijay Abraham I <kishon@kernel.org> | R:	Kishon Vijay Abraham I <kishon@kernel.org> | ||||||
| L:	linux-pci@vger.kernel.org | L:	linux-pci@vger.kernel.org | ||||||
| S:	Supported | S:	Supported | ||||||
|  | @ -19058,8 +19059,8 @@ F:	drivers/pci/controller/pci-xgene-msi.c | ||||||
| 
 | 
 | ||||||
| PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS | PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS | ||||||
| M:	Lorenzo Pieralisi <lpieralisi@kernel.org> | M:	Lorenzo Pieralisi <lpieralisi@kernel.org> | ||||||
| M:	Krzysztof Wilczyński <kw@linux.com> | M:	Krzysztof Wilczyński <kwilczynski@kernel.org> | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| R:	Rob Herring <robh@kernel.org> | R:	Rob Herring <robh@kernel.org> | ||||||
| L:	linux-pci@vger.kernel.org | L:	linux-pci@vger.kernel.org | ||||||
| S:	Supported | S:	Supported | ||||||
|  | @ -19067,6 +19068,7 @@ Q:	https://patchwork.kernel.org/project/linux-pci/list/ | ||||||
| B:	https://bugzilla.kernel.org | B:	https://bugzilla.kernel.org | ||||||
| C:	irc://irc.oftc.net/linux-pci | C:	irc://irc.oftc.net/linux-pci | ||||||
| T:	git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git | 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:	Documentation/devicetree/bindings/pci/ | ||||||
| F:	drivers/pci/controller/ | F:	drivers/pci/controller/ | ||||||
| F:	drivers/pci/pci-bridge-emul.c | F:	drivers/pci/pci-bridge-emul.c | ||||||
|  | @ -19215,7 +19217,7 @@ F:	Documentation/devicetree/bindings/pci/microchip* | ||||||
| F:	drivers/pci/controller/plda/*microchip* | F:	drivers/pci/controller/plda/*microchip* | ||||||
| 
 | 
 | ||||||
| PCIE DRIVER FOR QUALCOMM MSM | 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-pci@vger.kernel.org | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -19251,7 +19253,7 @@ F:	Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml | ||||||
| F:	drivers/pci/controller/plda/pcie-starfive.c | F:	drivers/pci/controller/plda/pcie-starfive.c | ||||||
| 
 | 
 | ||||||
| PCIE ENDPOINT DRIVER FOR QUALCOMM | 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-pci@vger.kernel.org | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -20379,7 +20381,7 @@ F:	drivers/iommu/arm/arm-smmu/arm-smmu-qcom* | ||||||
| F:	drivers/iommu/msm_iommu* | F:	drivers/iommu/msm_iommu* | ||||||
| 
 | 
 | ||||||
| QUALCOMM IPC ROUTER (QRTR) DRIVER | 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 | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	include/trace/events/qrtr.h | F:	include/trace/events/qrtr.h | ||||||
|  | @ -20387,7 +20389,7 @@ F:	include/uapi/linux/qrtr.h | ||||||
| F:	net/qrtr/ | F:	net/qrtr/ | ||||||
| 
 | 
 | ||||||
| QUALCOMM IPCC MAILBOX DRIVER | QUALCOMM IPCC MAILBOX DRIVER | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Supported | S:	Supported | ||||||
| F:	Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml | 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/ | F:	drivers/media/platform/qcom/iris/ | ||||||
| 
 | 
 | ||||||
| QUALCOMM NAND CONTROLLER DRIVER | 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-mtd@lists.infradead.org | ||||||
| L:	linux-arm-msm@vger.kernel.org | L:	linux-arm-msm@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  | @ -22990,7 +22992,7 @@ F:	Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml | ||||||
| F:	drivers/media/i2c/imx283.c | F:	drivers/media/i2c/imx283.c | ||||||
| 
 | 
 | ||||||
| SONY IMX290 SENSOR DRIVER | SONY IMX290 SENSOR DRIVER | ||||||
| M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | M:	Manivannan Sadhasivam <mani@kernel.org> | ||||||
| L:	linux-media@vger.kernel.org | L:	linux-media@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| T:	git git://linuxtv.org/media.git | T:	git git://linuxtv.org/media.git | ||||||
|  | @ -22999,7 +23001,7 @@ F:	drivers/media/i2c/imx290.c | ||||||
| 
 | 
 | ||||||
| SONY IMX296 SENSOR DRIVER | SONY IMX296 SENSOR DRIVER | ||||||
| M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 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 | L:	linux-media@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| T:	git git://linuxtv.org/media.git | T:	git git://linuxtv.org/media.git | ||||||
|  | @ -25374,7 +25376,7 @@ S:	Maintained | ||||||
| F:	drivers/ufs/host/ufs-mediatek* | F:	drivers/ufs/host/ufs-mediatek* | ||||||
| 
 | 
 | ||||||
| UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER QUALCOMM HOOKS | 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-arm-msm@vger.kernel.org | ||||||
| L:	linux-scsi@vger.kernel.org | L:	linux-scsi@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  |  | ||||||
|  | @ -269,7 +269,7 @@ config ARCH_QCOM | ||||||
| 	bool "Qualcomm Platforms" | 	bool "Qualcomm Platforms" | ||||||
| 	select GPIOLIB | 	select GPIOLIB | ||||||
| 	select PINCTRL | 	select PINCTRL | ||||||
| 	select HAVE_PWRCTL if PCI | 	select HAVE_PWRCTRL if PCI | ||||||
| 	help | 	help | ||||||
| 	  This enables support for the ARMv8 based Qualcomm chipsets. | 	  This enables support for the ARMv8 based Qualcomm chipsets. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,13 +8,13 @@ obj-$(CONFIG_PCI_OLPC)		+= olpc.o | ||||||
| obj-$(CONFIG_PCI_XEN)		+= xen.o | obj-$(CONFIG_PCI_XEN)		+= xen.o | ||||||
| 
 | 
 | ||||||
| obj-y				+= fixup.o | obj-y				+= fixup.o | ||||||
| obj-$(CONFIG_X86_INTEL_CE)      += ce4100.o |  | ||||||
| obj-$(CONFIG_ACPI)		+= acpi.o | obj-$(CONFIG_ACPI)		+= acpi.o | ||||||
| obj-y				+= legacy.o irq.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				+= common.o early.o | ||||||
| obj-y				+= bus_numa.o | obj-y				+= bus_numa.o | ||||||
|  |  | ||||||
|  | @ -8,7 +8,6 @@ config DRM_ACCEL_QAIC | ||||||
| 	depends on DRM_ACCEL | 	depends on DRM_ACCEL | ||||||
| 	depends on PCI && HAS_IOMEM | 	depends on PCI && HAS_IOMEM | ||||||
| 	depends on MHI_BUS | 	depends on MHI_BUS | ||||||
| 	depends on MMU |  | ||||||
| 	select CRC32 | 	select CRC32 | ||||||
| 	help | 	help | ||||||
| 	  Enables driver for Qualcomm's Cloud AI accelerator PCIe cards that are | 	  Enables driver for Qualcomm's Cloud AI accelerator PCIe cards that are | ||||||
|  |  | ||||||
|  | @ -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)); | 	rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | ||||||
| 	if (rv) { | 	if (rv) { | ||||||
| 		dev_warn(&pdev->dev, "64-bit DMA enable failed\n"); | 		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. */ | 	/* 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) { | 	if (!dd->isr_workq) { | ||||||
| 		dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance); | 		dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance); | ||||||
| 		rv = -ENOMEM; | 		rv = -ENOMEM; | ||||||
| 		goto setmask_err; | 		goto iomap_err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	memset(cpu_list, 0, sizeof(cpu_list)); | 	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[1].cpu_binding); | ||||||
| 		drop_cpu(dd->work[2].cpu_binding); | 		drop_cpu(dd->work[2].cpu_binding); | ||||||
| 	} | 	} | ||||||
| setmask_err: |  | ||||||
| 	pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); |  | ||||||
| 
 | 
 | ||||||
| iomap_err: | iomap_err: | ||||||
| 	kfree(dd); | 	kfree(dd); | ||||||
|  | @ -3907,7 +3905,6 @@ static void mtip_pci_remove(struct pci_dev *pdev) | ||||||
| 
 | 
 | ||||||
| 	pci_disable_msi(pdev); | 	pci_disable_msi(pdev); | ||||||
| 
 | 
 | ||||||
| 	pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); |  | ||||||
| 	pci_set_drvdata(pdev, NULL); | 	pci_set_drvdata(pdev, NULL); | ||||||
| 
 | 
 | ||||||
| 	put_disk(dd->disk); | 	put_disk(dd->disk); | ||||||
|  |  | ||||||
|  | @ -83,7 +83,7 @@ config FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST | ||||||
| 
 | 
 | ||||||
| config FIREWIRE_OHCI | config FIREWIRE_OHCI | ||||||
| 	tristate "OHCI-1394 controllers" | 	tristate "OHCI-1394 controllers" | ||||||
| 	depends on PCI && FIREWIRE && MMU | 	depends on PCI && FIREWIRE | ||||||
| 	help | 	help | ||||||
| 	  Enable this driver if you have a FireWire controller based | 	  Enable this driver if you have a FireWire controller based | ||||||
| 	  on the OHCI specification.  For all practical purposes, this | 	  on the OHCI specification.  For all practical purposes, this | ||||||
|  |  | ||||||
|  | @ -398,7 +398,7 @@ source "drivers/gpu/drm/imagination/Kconfig" | ||||||
| 
 | 
 | ||||||
| config DRM_HYPERV | config DRM_HYPERV | ||||||
| 	tristate "DRM Support for Hyper-V synthetic video device" | 	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_CLIENT_SELECTION | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
| 	select DRM_GEM_SHMEM_HELPER | 	select DRM_GEM_SHMEM_HELPER | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| config DRM_AMDGPU | config DRM_AMDGPU | ||||||
| 	tristate "AMD GPU" | 	tristate "AMD GPU" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	depends on !UML | 	depends on !UML | ||||||
| 	select FW_LOADER | 	select FW_LOADER | ||||||
| 	select DRM_CLIENT | 	select DRM_CLIENT | ||||||
|  | @ -68,7 +68,6 @@ config DRM_AMDGPU_CIK | ||||||
| config DRM_AMDGPU_USERPTR | config DRM_AMDGPU_USERPTR | ||||||
| 	bool "Always enable userptr write support" | 	bool "Always enable userptr write support" | ||||||
| 	depends on DRM_AMDGPU | 	depends on DRM_AMDGPU | ||||||
| 	depends on MMU |  | ||||||
| 	select HMM_MIRROR | 	select HMM_MIRROR | ||||||
| 	select MMU_NOTIFIER | 	select MMU_NOTIFIER | ||||||
| 	help | 	help | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_AST | config DRM_AST | ||||||
| 	tristate "AST server chips" | 	tristate "AST server chips" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_GEM_SHMEM_HELPER | 	select DRM_GEM_SHMEM_HELPER | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_GMA500 | config DRM_GMA500 | ||||||
| 	tristate "Intel GMA500/600/3600/3650 KMS Framebuffer" | 	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_CLIENT_SELECTION | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
| 	select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION | 	select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ | ||||||
| config DRM_HISI_HIBMC | config DRM_HISI_HIBMC | ||||||
| 	tristate "DRM Support for Hisilicon Hibmc" | 	tristate "DRM Support for Hisilicon Hibmc" | ||||||
| 	depends on DRM && PCI | 	depends on DRM && PCI | ||||||
| 	depends on MMU |  | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_DISPLAY_HELPER | 	select DRM_DISPLAY_HELPER | ||||||
| 	select DRM_DISPLAY_DP_HELPER | 	select DRM_DISPLAY_DP_HELPER | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| config DRM_LOONGSON | config DRM_LOONGSON | ||||||
| 	tristate "DRM support for Loongson Graphics" | 	tristate "DRM support for Loongson Graphics" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	depends on LOONGARCH || MIPS || COMPILE_TEST | 	depends on LOONGARCH || MIPS || COMPILE_TEST | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_MGAG200 | config DRM_MGAG200 | ||||||
| 	tristate "Matrox G200" | 	tristate "Matrox G200" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_GEM_SHMEM_HELPER | 	select DRM_GEM_SHMEM_HELPER | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_NOUVEAU | config DRM_NOUVEAU | ||||||
| 	tristate "Nouveau (NVIDIA) cards" | 	tristate "Nouveau (NVIDIA) cards" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	select IOMMU_API | 	select IOMMU_API | ||||||
| 	select FW_LOADER | 	select FW_LOADER | ||||||
| 	select FW_CACHE if PM_SLEEP | 	select FW_CACHE if PM_SLEEP | ||||||
|  | @ -94,7 +94,6 @@ config DRM_NOUVEAU_SVM | ||||||
| 	bool "(EXPERIMENTAL) Enable SVM (Shared Virtual Memory) support" | 	bool "(EXPERIMENTAL) Enable SVM (Shared Virtual Memory) support" | ||||||
| 	depends on DEVICE_PRIVATE | 	depends on DEVICE_PRIVATE | ||||||
| 	depends on DRM_NOUVEAU | 	depends on DRM_NOUVEAU | ||||||
| 	depends on MMU |  | ||||||
| 	depends on STAGING | 	depends on STAGING | ||||||
| 	select HMM_MIRROR | 	select HMM_MIRROR | ||||||
| 	select MMU_NOTIFIER | 	select MMU_NOTIFIER | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_QXL | config DRM_QXL | ||||||
| 	tristate "QXL virtual GPU" | 	tristate "QXL virtual GPU" | ||||||
| 	depends on DRM && PCI && MMU && HAS_IOPORT | 	depends on DRM && PCI && HAS_IOPORT | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
| 	select DRM_TTM | 	select DRM_TTM | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| config DRM_RADEON | config DRM_RADEON | ||||||
| 	tristate "ATI Radeon" | 	tristate "ATI Radeon" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	depends on AGP || !AGP | 	depends on AGP || !AGP | ||||||
| 	select FW_LOADER | 	select FW_LOADER | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ config DRM_BOCHS | ||||||
| 
 | 
 | ||||||
| config DRM_CIRRUS_QEMU | config DRM_CIRRUS_QEMU | ||||||
| 	tristate "Cirrus driver for QEMU emulated device" | 	tristate "Cirrus driver for QEMU emulated device" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_KMS_HELPER | 	select DRM_KMS_HELPER | ||||||
| 	select DRM_GEM_SHMEM_HELPER | 	select DRM_GEM_SHMEM_HELPER | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0 | # SPDX-License-Identifier: GPL-2.0 | ||||||
| config DRM_VMWGFX | config DRM_VMWGFX | ||||||
| 	tristate "DRM driver for VMware Virtual GPU" | 	tristate "DRM driver for VMware Virtual GPU" | ||||||
| 	depends on DRM && PCI && MMU | 	depends on DRM && PCI | ||||||
| 	depends on (X86 && HYPERVISOR_GUEST) || ARM64 | 	depends on (X86 && HYPERVISOR_GUEST) || ARM64 | ||||||
| 	select DRM_CLIENT_SELECTION | 	select DRM_CLIENT_SELECTION | ||||||
| 	select DRM_TTM | 	select DRM_TTM | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0-only | # SPDX-License-Identifier: GPL-2.0-only | ||||||
| config DRM_XE | config DRM_XE | ||||||
| 	tristate "Intel Xe Graphics" | 	tristate "Intel Xe Graphics" | ||||||
| 	depends on DRM && PCI && MMU && (m || (y && KUNIT=y)) | 	depends on DRM && PCI && (m || (y && KUNIT=y)) | ||||||
| 	select INTERVAL_TREE | 	select INTERVAL_TREE | ||||||
| 	# we need shmfs for the swappable backing store, and in particular | 	# we need shmfs for the swappable backing store, and in particular | ||||||
| 	# the shmem_readpage() which depends upon tmpfs | 	# the shmem_readpage() which depends upon tmpfs | ||||||
|  |  | ||||||
|  | @ -2024,9 +2024,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) | ||||||
| 	if (!iommu->dev) | 	if (!iommu->dev) | ||||||
| 		return -ENODEV; | 		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 */ | 	/* ACPI _PRT won't have an IRQ for IOMMU */ | ||||||
| 	iommu->dev->irq_managed = 1; | 	iommu->dev->irq_managed = 1; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,7 +96,6 @@ config BNX2 | ||||||
| config CNIC | config CNIC | ||||||
| 	tristate "QLogic CNIC support" | 	tristate "QLogic CNIC support" | ||||||
| 	depends on PCI && (IPV6 || IPV6=n) | 	depends on PCI && (IPV6 || IPV6=n) | ||||||
| 	depends on MMU |  | ||||||
| 	select BNX2 | 	select BNX2 | ||||||
| 	select UIO | 	select UIO | ||||||
| 	help | 	help | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ config ATH11K_PCI | ||||||
| 	select MHI_BUS | 	select MHI_BUS | ||||||
| 	select QRTR | 	select QRTR | ||||||
| 	select QRTR_MHI | 	select QRTR_MHI | ||||||
| 	select PCI_PWRCTL_PWRSEQ if HAVE_PWRCTL | 	select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL | ||||||
| 	help | 	help | ||||||
| 	  This module adds support for PCIE bus | 	  This module adds support for PCIE bus | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ config ATH12K | ||||||
| 	select MHI_BUS | 	select MHI_BUS | ||||||
| 	select QRTR | 	select QRTR | ||||||
| 	select QRTR_MHI | 	select QRTR_MHI | ||||||
| 	select PCI_PWRCTL_PWRSEQ if HAVE_PWRCTL | 	select PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL | ||||||
| 	help | 	help | ||||||
| 	  Enable support for Qualcomm Technologies Wi-Fi 7 (IEEE | 	  Enable support for Qualcomm Technologies Wi-Fi 7 (IEEE | ||||||
| 	  802.11be) family of chipsets, for example WCN7850 and | 	  802.11be) family of chipsets, for example WCN7850 and | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ config GENERIC_PCI_IOMAP | ||||||
| menuconfig PCI | menuconfig PCI | ||||||
| 	bool "PCI support" | 	bool "PCI support" | ||||||
| 	depends on HAVE_PCI | 	depends on HAVE_PCI | ||||||
|  | 	depends on MMU | ||||||
| 	help | 	help | ||||||
| 	  This option enables support for the PCI local bus, including | 	  This option enables support for the PCI local bus, including | ||||||
| 	  support for PCI-X and the foundations for PCI Express support. | 	  support for PCI-X and the foundations for PCI Express support. | ||||||
|  |  | ||||||
|  | @ -369,7 +369,9 @@ void pci_bus_add_device(struct pci_dev *dev) | ||||||
| 				pdev->name); | 				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); | 	retval = device_attach(&dev->dev); | ||||||
| 	if (retval < 0 && retval != -EPROBE_DEFER) | 	if (retval < 0 && retval != -EPROBE_DEFER) | ||||||
| 		pci_warn(dev, "device attach failed (%d)\n", retval); | 		pci_warn(dev, "device attach failed (%d)\n", retval); | ||||||
|  |  | ||||||
|  | @ -3,6 +3,10 @@ | ||||||
| menu "PCI controller drivers" | menu "PCI controller drivers" | ||||||
| 	depends on PCI | 	depends on PCI | ||||||
| 
 | 
 | ||||||
|  | config PCI_HOST_COMMON | ||||||
|  | 	tristate | ||||||
|  | 	select PCI_ECAM | ||||||
|  | 
 | ||||||
| config PCI_AARDVARK | config PCI_AARDVARK | ||||||
| 	tristate "Aardvark PCIe controller" | 	tristate "Aardvark PCIe controller" | ||||||
| 	depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST | 	depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST | ||||||
|  | @ -120,10 +124,6 @@ config PCI_FTPCI100 | ||||||
| 	depends on OF | 	depends on OF | ||||||
| 	default ARCH_GEMINI | 	default ARCH_GEMINI | ||||||
| 
 | 
 | ||||||
| config PCI_HOST_COMMON |  | ||||||
| 	tristate |  | ||||||
| 	select PCI_ECAM |  | ||||||
| 
 |  | ||||||
| config PCI_HOST_GENERIC | config PCI_HOST_GENERIC | ||||||
| 	tristate "Generic PCI host controller" | 	tristate "Generic PCI host controller" | ||||||
| 	depends on OF | 	depends on OF | ||||||
|  |  | ||||||
|  | @ -4,16 +4,16 @@ menu "Cadence-based PCIe controllers" | ||||||
| 	depends on PCI | 	depends on PCI | ||||||
| 
 | 
 | ||||||
| config PCIE_CADENCE | config PCIE_CADENCE | ||||||
| 	bool | 	tristate | ||||||
| 
 | 
 | ||||||
| config PCIE_CADENCE_HOST | config PCIE_CADENCE_HOST | ||||||
| 	bool | 	tristate | ||||||
| 	depends on OF | 	depends on OF | ||||||
| 	select IRQ_DOMAIN | 	select IRQ_DOMAIN | ||||||
| 	select PCIE_CADENCE | 	select PCIE_CADENCE | ||||||
| 
 | 
 | ||||||
| config PCIE_CADENCE_EP | config PCIE_CADENCE_EP | ||||||
| 	bool | 	tristate | ||||||
| 	depends on OF | 	depends on OF | ||||||
| 	depends on PCI_ENDPOINT | 	depends on PCI_ENDPOINT | ||||||
| 	select PCIE_CADENCE | 	select PCIE_CADENCE | ||||||
|  | @ -43,13 +43,14 @@ config PCIE_CADENCE_PLAT_EP | ||||||
| 	  different vendors SoCs. | 	  different vendors SoCs. | ||||||
| 
 | 
 | ||||||
| config PCI_J721E | 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 | 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 ARCH_K3 || COMPILE_TEST | ||||||
| 	depends on OF | 	depends on OF | ||||||
| 	select PCIE_CADENCE_HOST |  | ||||||
| 	select PCI_J721E | 	select PCI_J721E | ||||||
| 	help | 	help | ||||||
| 	  Say Y here if you want to support the TI J721E PCIe platform | 	  Say Y here if you want to support the TI J721E PCIe platform | ||||||
|  | @ -57,11 +58,10 @@ config PCI_J721E_HOST | ||||||
| 	  core. | 	  core. | ||||||
| 
 | 
 | ||||||
| config PCI_J721E_EP | 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 ARCH_K3 || COMPILE_TEST | ||||||
| 	depends on OF | 	depends on OF | ||||||
| 	depends on PCI_ENDPOINT | 	depends on PCI_ENDPOINT | ||||||
| 	select PCIE_CADENCE_EP |  | ||||||
| 	select PCI_J721E | 	select PCI_J721E | ||||||
| 	help | 	help | ||||||
| 	  Say Y here if you want to support the TI J721E PCIe platform | 	  Say Y here if you want to support the TI J721E PCIe platform | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ | ||||||
| #include <linux/irqchip/chained_irq.h> | #include <linux/irqchip/chained_irq.h> | ||||||
| #include <linux/irqdomain.h> | #include <linux/irqdomain.h> | ||||||
| #include <linux/mfd/syscon.h> | #include <linux/mfd/syscon.h> | ||||||
|  | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| #include <linux/pci.h> | #include <linux/pci.h> | ||||||
| #include <linux/platform_device.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 cdns_pcie_to_rc(p) container_of(p, struct cdns_pcie_rc, pcie) | ||||||
| 
 | 
 | ||||||
| #define ENABLE_REG_SYS_2	0x108 | #define ENABLE_REG_SYS_2	0x108 | ||||||
|  | #define ENABLE_CLR_REG_SYS_2	0x308 | ||||||
| #define STATUS_REG_SYS_2	0x508 | #define STATUS_REG_SYS_2	0x508 | ||||||
| #define STATUS_CLR_REG_SYS_2	0x708 | #define STATUS_CLR_REG_SYS_2	0x708 | ||||||
| #define LINK_DOWN		BIT(1) | #define LINK_DOWN		BIT(1) | ||||||
|  | @ -116,6 +118,15 @@ static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv) | ||||||
| 	return IRQ_HANDLED; | 	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) | static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie) | ||||||
| { | { | ||||||
| 	u32 reg; | 	u32 reg; | ||||||
|  | @ -153,11 +164,7 @@ static bool j721e_pcie_link_up(struct cdns_pcie *cdns_pcie) | ||||||
| 	u32 reg; | 	u32 reg; | ||||||
| 
 | 
 | ||||||
| 	reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_LINKSTATUS); | 	reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_LINKSTATUS); | ||||||
| 	reg &= LINK_STATUS; | 	return (reg & LINK_STATUS) == LINK_UP_DL_COMPLETED; | ||||||
| 	if (reg == LINK_UP_DL_COMPLETED) |  | ||||||
| 		return true; |  | ||||||
| 
 |  | ||||||
| 	return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct cdns_pcie_ops j721e_pcie_ops = { | static const struct cdns_pcie_ops j721e_pcie_ops = { | ||||||
|  | @ -464,7 +471,7 @@ static int j721e_pcie_probe(struct platform_device *pdev) | ||||||
| 
 | 
 | ||||||
| 	switch (mode) { | 	switch (mode) { | ||||||
| 	case PCI_MODE_RC: | 	case PCI_MODE_RC: | ||||||
| 		if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)) | 		if (!IS_ENABLED(CONFIG_PCI_J721E_HOST)) | ||||||
| 			return -ENODEV; | 			return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 		bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); | 		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; | 		pcie->cdns_pcie = cdns_pcie; | ||||||
| 		break; | 		break; | ||||||
| 	case PCI_MODE_EP: | 	case PCI_MODE_EP: | ||||||
| 		if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP)) | 		if (!IS_ENABLED(CONFIG_PCI_J721E_EP)) | ||||||
| 			return -ENODEV; | 			return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 		ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); | 		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 j721e_pcie *pcie = platform_get_drvdata(pdev); | ||||||
| 	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; | 	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; | ||||||
| 	struct device *dev = &pdev->dev; | 	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); | 	clk_disable_unprepare(pcie->refclk); | ||||||
| 	cdns_pcie_disable_phy(cdns_pcie); | 	cdns_pcie_disable_phy(cdns_pcie); | ||||||
|  | 	j721e_pcie_disable_link_irq(pcie); | ||||||
| 	pm_runtime_put(dev); | 	pm_runtime_put(dev); | ||||||
| 	pm_runtime_disable(dev); | 	pm_runtime_disable(dev); | ||||||
| } | } | ||||||
|  | @ -730,4 +750,8 @@ static struct platform_driver j721e_pcie_driver = { | ||||||
| 		.pm	= pm_sleep_ptr(&j721e_pcie_pm_ops), | 		.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>"); | ||||||
|  |  | ||||||
|  | @ -6,12 +6,14 @@ | ||||||
| #include <linux/bitfield.h> | #include <linux/bitfield.h> | ||||||
| #include <linux/delay.h> | #include <linux/delay.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| #include <linux/pci-epc.h> | #include <linux/pci-epc.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| #include <linux/sizes.h> | #include <linux/sizes.h> | ||||||
| 
 | 
 | ||||||
| #include "pcie-cadence.h" | #include "pcie-cadence.h" | ||||||
|  | #include "../../pci.h" | ||||||
| 
 | 
 | ||||||
| #define CDNS_PCIE_EP_MIN_APERTURE		128	/* 128 bytes */ | #define CDNS_PCIE_EP_MIN_APERTURE		128	/* 128 bytes */ | ||||||
| #define CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE		0x1 | #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); | 	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_ep *ep = epc_get_drvdata(epc); | ||||||
| 	struct cdns_pcie *pcie = &ep->pcie; | 	struct cdns_pcie *pcie = &ep->pcie; | ||||||
|  | 	u8 mmc = order_base_2(nr_irqs); | ||||||
| 	u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET; | 	u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET; | ||||||
| 	u16 flags; | 	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); | 	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) | 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; | 	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, | static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn, | ||||||
| 				 u16 interrupts, enum pci_barno bir, | 				 u16 nr_irqs, enum pci_barno bir, u32 offset) | ||||||
| 				 u32 offset) |  | ||||||
| { | { | ||||||
| 	struct cdns_pcie_ep *ep = epc_get_drvdata(epc); | 	struct cdns_pcie_ep *ep = epc_get_drvdata(epc); | ||||||
| 	struct cdns_pcie *pcie = &ep->pcie; | 	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; | 	reg = cap + PCI_MSIX_FLAGS; | ||||||
| 	val = cdns_pcie_ep_fn_readw(pcie, fn, reg); | 	val = cdns_pcie_ep_fn_readw(pcie, fn, reg); | ||||||
| 	val &= ~PCI_MSIX_FLAGS_QSIZE; | 	val &= ~PCI_MSIX_FLAGS_QSIZE; | ||||||
| 	val |= interrupts; | 	val |= nr_irqs - 1; /* encoded as N-1 */ | ||||||
| 	cdns_pcie_ep_fn_writew(pcie, fn, reg, val); | 	cdns_pcie_ep_fn_writew(pcie, fn, reg, val); | ||||||
| 
 | 
 | ||||||
| 	/* Set MSI-X BAR and offset */ | 	/* 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 */ | 	/* Set PBA BAR and offset.  BAR must match MSI-X BAR */ | ||||||
| 	reg = cap + PCI_MSIX_PBA; | 	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); | 	cdns_pcie_ep_fn_writel(pcie, fn, reg, val); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	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) { | 	if (is_asserted) { | ||||||
| 		ep->irq_pending |= BIT(intx); | 		ep->irq_pending |= BIT(intx); | ||||||
| 		msg_code = MSG_CODE_ASSERT_INTA + intx; | 		msg_code = PCIE_MSG_CODE_ASSERT_INTA + intx; | ||||||
| 	} else { | 	} else { | ||||||
| 		ep->irq_pending &= ~BIT(intx); | 		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); | 	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, | 	.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) | 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; | 	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>"); | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/delay.h> | #include <linux/delay.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/module.h> | ||||||
| #include <linux/list_sort.h> | #include <linux/list_sort.h> | ||||||
| #include <linux/of_address.h> | #include <linux/of_address.h> | ||||||
| #include <linux/of_pci.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); | 	return rc->cfg_base + (where & 0xfff); | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(cdns_pci_map_bus); | ||||||
| 
 | 
 | ||||||
| static struct pci_ops cdns_pcie_host_ops = { | static struct pci_ops cdns_pcie_host_ops = { | ||||||
| 	.map_bus	= cdns_pci_map_bus, | 	.map_bus	= cdns_pci_map_bus, | ||||||
|  | @ -150,6 +152,14 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie) | ||||||
| 	return ret; | 	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) | static void cdns_pcie_host_enable_ptm_response(struct cdns_pcie *pcie) | ||||||
| { | { | ||||||
| 	u32 val; | 	u32 val; | ||||||
|  | @ -175,6 +185,26 @@ static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc) | ||||||
| 	return ret; | 	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) | static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc) | ||||||
| { | { | ||||||
| 	struct cdns_pcie *pcie = &rc->pcie; | 	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); |         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) | static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc) | ||||||
| { | { | ||||||
| 	struct cdns_pcie *pcie = &rc->pcie; | 	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; | 	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) | static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc) | ||||||
| { | { | ||||||
| 	struct cdns_pcie *pcie = &rc->pcie; | 	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); | 	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 cdns_pcie_host_init(struct cdns_pcie_rc *rc) | ||||||
| { | { | ||||||
| 	int err; | 	int err; | ||||||
|  | @ -495,6 +580,15 @@ int cdns_pcie_host_init(struct cdns_pcie_rc *rc) | ||||||
| 
 | 
 | ||||||
| 	return cdns_pcie_host_init_address_translation(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) | 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; | 	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) | 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) | 	if (!bridge->ops) | ||||||
| 		bridge->ops = &cdns_pcie_host_ops; | 		bridge->ops = &cdns_pcie_host_ops; | ||||||
| 
 | 
 | ||||||
| 	ret = pci_host_probe(bridge); | 	return pci_host_probe(bridge); | ||||||
| 	if (ret < 0) |  | ||||||
| 		goto err_init; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| 
 |  | ||||||
|  err_init: |  | ||||||
| 	pm_runtime_put_sync(dev); |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
|  | 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>"); | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
 | // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
 | ||||||
| 
 | 
 | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| 
 | 
 | ||||||
| #include "pcie-cadence.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); | 	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, | void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn, | ||||||
| 				   u32 r, bool is_io, | 				   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_ADDR0(r), addr0); | ||||||
| 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1); | 	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, | void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, | ||||||
| 						  u8 busnr, u8 fn, | 						  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_ADDR0(r), addr0); | ||||||
| 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1); | 	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) | 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_ADDR0(r), 0); | ||||||
| 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(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) | 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]); | 		phy_exit(pcie->phy[i]); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(cdns_pcie_disable_phy); | ||||||
| 
 | 
 | ||||||
| int cdns_pcie_enable_phy(struct cdns_pcie *pcie) | int cdns_pcie_enable_phy(struct cdns_pcie *pcie) | ||||||
| { | { | ||||||
|  | @ -184,6 +190,7 @@ int cdns_pcie_enable_phy(struct cdns_pcie *pcie) | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(cdns_pcie_enable_phy); | ||||||
| 
 | 
 | ||||||
| int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie) | 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; | 	return ret; | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(cdns_pcie_init_phy); | ||||||
| 
 | 
 | ||||||
| static int cdns_pcie_suspend_noirq(struct device *dev) | 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, | 	NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq, | ||||||
| 				  cdns_pcie_resume_noirq) | 				  cdns_pcie_resume_noirq) | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
|  | MODULE_DESCRIPTION("Cadence PCIe controller driver"); | ||||||
|  | MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@free-electrons.com>"); | ||||||
|  |  | ||||||
|  | @ -250,17 +250,6 @@ struct cdns_pcie_rp_ib_bar { | ||||||
| 
 | 
 | ||||||
| struct cdns_pcie; | 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 { | enum cdns_pcie_msg_routing { | ||||||
| 	/* Route to Root Complex */ | 	/* Route to Root Complex */ | ||||||
| 	MSG_ROUTING_TO_RC, | 	MSG_ROUTING_TO_RC, | ||||||
|  | @ -519,10 +508,11 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie) | ||||||
| 	return true; | 	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_link_setup(struct cdns_pcie_rc *rc); | ||||||
| int cdns_pcie_host_init(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); | 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, | void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, | ||||||
| 			       int where); | 			       int where); | ||||||
| #else | #else | ||||||
|  | @ -541,6 +531,10 @@ static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc) | ||||||
| 	return 0; | 	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, | static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, | ||||||
| 					     int where) | 					     int where) | ||||||
| { | { | ||||||
|  | @ -548,13 +542,18 @@ static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int d | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_PCIE_CADENCE_EP | #if IS_ENABLED(CONFIG_PCIE_CADENCE_EP) | ||||||
| int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep); | int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep); | ||||||
|  | void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep); | ||||||
| #else | #else | ||||||
| static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep) | static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep) | ||||||
| { | { | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static inline void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep) | ||||||
|  | { | ||||||
|  | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie); | void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie *pcie); | ||||||
|  |  | ||||||
|  | @ -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; | 	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); | 	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); | ||||||
| 	u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); | 	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) | static void dra7xx_pcie_stop_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -209,12 +209,12 @@ static struct pci_ops exynos_pci_ops = { | ||||||
| 	.write = exynos_pcie_wr_own_conf, | 	.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); | 	struct exynos_pcie *ep = to_exynos_pcie(pci); | ||||||
| 	u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); | 	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) | static int exynos_pcie_host_init(struct dw_pcie_rp *pp) | ||||||
|  |  | ||||||
|  | @ -45,9 +45,14 @@ | ||||||
| #define IMX95_PCIE_PHY_GEN_CTRL			0x0 | #define IMX95_PCIE_PHY_GEN_CTRL			0x0 | ||||||
| #define IMX95_PCIE_REF_USE_PAD			BIT(17) | #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_SS_RW_REG_0			0xf0 | ||||||
| #define IMX95_PCIE_REF_CLKEN			BIT(23) | #define IMX95_PCIE_REF_CLKEN			BIT(23) | ||||||
| #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9) | #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_PE0_GEN_CTRL_1			0x1050 | ||||||
| #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0) | #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0) | ||||||
|  | @ -71,6 +76,9 @@ | ||||||
| #define IMX95_SID_MASK				GENMASK(5, 0) | #define IMX95_SID_MASK				GENMASK(5, 0) | ||||||
| #define IMX95_MAX_LUT				32 | #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) | #define to_imx_pcie(x)	dev_get_drvdata((x)->dev) | ||||||
| 
 | 
 | ||||||
| enum imx_pcie_variants { | 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_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_SUPPORTS_SUSPEND		BIT(2) | ||||||
| #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3) | #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3) | ||||||
| #define IMX_PCIE_FLAG_HAS_APP_RESET		BIT(4) | #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_BROKEN_SUSPEND		BIT(9) | ||||||
| #define IMX_PCIE_FLAG_HAS_LUT			BIT(10) | #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) | #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 (*init_phy)(struct imx_pcie *pcie); | ||||||
| 	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable); | 	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable); | ||||||
| 	int (*core_reset)(struct imx_pcie *pcie, bool assert); | 	int (*core_reset)(struct imx_pcie *pcie, bool assert); | ||||||
|  | 	int (*wait_pll_lock)(struct imx_pcie *pcie); | ||||||
| 	const struct dw_pcie_host_ops *ops; | 	const struct dw_pcie_host_ops *ops; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct imx_lut_data { | ||||||
|  | 	u32 data1; | ||||||
|  | 	u32 data2; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct imx_pcie { | struct imx_pcie { | ||||||
| 	struct dw_pcie		*pci; | 	struct dw_pcie		*pci; | ||||||
| 	struct gpio_desc	*reset_gpiod; | 	struct gpio_desc	*reset_gpiod; | ||||||
|  | @ -148,6 +163,8 @@ struct imx_pcie { | ||||||
| 	struct regulator	*vph; | 	struct regulator	*vph; | ||||||
| 	void __iomem		*phy_base; | 	void __iomem		*phy_base; | ||||||
| 
 | 
 | ||||||
|  | 	/* LUT data for pcie */ | ||||||
|  | 	struct imx_lut_data	luts[IMX95_MAX_LUT]; | ||||||
| 	/* power domain for pcie */ | 	/* power domain for pcie */ | ||||||
| 	struct device		*pd_pcie; | 	struct device		*pd_pcie; | ||||||
| 	/* power domain for pcie phy */ | 	/* 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) | 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, | 	regmap_update_bits(imx_pcie->iomuxc_gpr, | ||||||
| 			IMX95_PCIE_SS_RW_REG_0, | 			IMX95_PCIE_SS_RW_REG_0, | ||||||
| 			IMX95_PCIE_PHY_CR_PARA_SEL, | 			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"); | 		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) | static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie) | ||||||
| { | { | ||||||
| 	unsigned long phy_rate = 0; | 	unsigned long phy_rate = 0; | ||||||
|  | @ -773,6 +820,43 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) | ||||||
| 	return 0; | 	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) | static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) | ||||||
| { | { | ||||||
| 	reset_control_assert(imx_pcie->pciephy_reset); | 	reset_control_assert(imx_pcie->pciephy_reset); | ||||||
|  | @ -860,6 +944,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci) | ||||||
| 	u32 tmp; | 	u32 tmp; | ||||||
| 	int ret; | 	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 | 	 * Force Gen1 operation when starting the link.  In case the link is | ||||||
| 	 * started in Gen2 mode, there is a possibility the devices on the | 	 * 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. */ | 	/* Start LTSSM. */ | ||||||
| 	imx_pcie_ltssm_enable(dev); | 	imx_pcie_ltssm_enable(dev); | ||||||
| 
 | 
 | ||||||
|  | 	if (pci->max_link_speed > 1) { | ||||||
| 		ret = dw_pcie_wait_for_link(pci); | 		ret = dw_pcie_wait_for_link(pci); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto err_reset_phy; | 			goto err_reset_phy; | ||||||
| 
 | 
 | ||||||
| 	if (pci->max_link_speed > 1) { |  | ||||||
| 		/* Allow faster modes after the link is up */ | 		/* Allow faster modes after the link is up */ | ||||||
| 		dw_pcie_dbi_ro_wr_en(pci); | 		dw_pcie_dbi_ro_wr_en(pci); | ||||||
| 		tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); | 		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_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); | ||||||
| 		dw_pcie_dbi_ro_wr_dis(pci); | 		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); | 		ret = imx_pcie_wait_for_speed_change(imx_pcie); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			dev_err(dev, "Failed to bring link up!\n"); | 			dev_err(dev, "Failed to bring link up!\n"); | ||||||
| 			goto err_reset_phy; | 			goto err_reset_phy; | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/* Make sure link training is finished as well! */ |  | ||||||
| 		ret = dw_pcie_wait_for_link(pci); |  | ||||||
| 		if (ret) |  | ||||||
| 			goto err_reset_phy; |  | ||||||
| 	} else { | 	} else { | ||||||
| 		dev_info(dev, "Link: Only Gen1 is enabled\n"); | 		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; | 	return 0; | ||||||
| 
 | 
 | ||||||
| err_reset_phy: | err_reset_phy: | ||||||
|  | @ -1182,6 +1253,12 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp) | ||||||
| 		goto err_phy_off; | 		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); | 	imx_setup_phy_mpll(imx_pcie); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -1214,6 +1291,32 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp) | ||||||
| 		regulator_disable(imx_pcie->vpcie); | 		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 |  * In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2 | ||||||
|  * register is reserved, so the generic DWC implementation of sending the |  * 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 = { | static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = { | ||||||
| 	.init = imx_pcie_host_init, | 	.init = imx_pcie_host_init, | ||||||
| 	.deinit = imx_pcie_host_exit, | 	.deinit = imx_pcie_host_exit, | ||||||
|  | 	.post_init = imx_pcie_host_post_init, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct dw_pcie_ops dw_pcie_ops = { | 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"); | 		dev_err(dev, "failed to initialize endpoint\n"); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
|  | 	imx_pcie_host_post_init(pp); | ||||||
| 
 | 
 | ||||||
| 	ret = dw_pcie_ep_init_registers(ep); | 	ret = dw_pcie_ep_init_registers(ep); | ||||||
| 	if (ret) { | 	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) | static int imx_pcie_suspend_noirq(struct device *dev) | ||||||
| { | { | ||||||
| 	struct imx_pcie *imx_pcie = dev_get_drvdata(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; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	imx_pcie_msi_save_restore(imx_pcie, true); | 	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)) { | 	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) { | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * The minimum for a workaround would be to set PERST# and to | 		 * 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) | 		if (ret) | ||||||
| 			return 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); | 	imx_pcie_msi_save_restore(imx_pcie, false); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -1649,7 +1794,7 @@ static const struct imx_pcie_drvdata drvdata[] = { | ||||||
| 	[IMX6Q] = { | 	[IMX6Q] = { | ||||||
| 		.variant = IMX6Q, | 		.variant = IMX6Q, | ||||||
| 		.flags = IMX_PCIE_FLAG_IMX_PHY | | 		.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_BROKEN_SUSPEND | | ||||||
| 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | ||||||
| 		.dbi_length = 0x200, | 		.dbi_length = 0x200, | ||||||
|  | @ -1665,7 +1810,7 @@ static const struct imx_pcie_drvdata drvdata[] = { | ||||||
| 	[IMX6SX] = { | 	[IMX6SX] = { | ||||||
| 		.variant = IMX6SX, | 		.variant = IMX6SX, | ||||||
| 		.flags = IMX_PCIE_FLAG_IMX_PHY | | 		.flags = IMX_PCIE_FLAG_IMX_PHY | | ||||||
| 			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE | | 			 IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND | | ||||||
| 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | ||||||
| 		.gpr = "fsl,imx6q-iomuxc-gpr", | 		.gpr = "fsl,imx6q-iomuxc-gpr", | ||||||
| 		.ltssm_off = IOMUXC_GPR12, | 		.ltssm_off = IOMUXC_GPR12, | ||||||
|  | @ -1680,7 +1825,7 @@ static const struct imx_pcie_drvdata drvdata[] = { | ||||||
| 	[IMX6QP] = { | 	[IMX6QP] = { | ||||||
| 		.variant = IMX6QP, | 		.variant = IMX6QP, | ||||||
| 		.flags = IMX_PCIE_FLAG_IMX_PHY | | 		.flags = IMX_PCIE_FLAG_IMX_PHY | | ||||||
| 			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE | | 			 IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND | | ||||||
| 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | ||||||
| 		.dbi_length = 0x200, | 		.dbi_length = 0x200, | ||||||
| 		.gpr = "fsl,imx6q-iomuxc-gpr", | 		.gpr = "fsl,imx6q-iomuxc-gpr", | ||||||
|  | @ -1747,12 +1892,15 @@ static const struct imx_pcie_drvdata drvdata[] = { | ||||||
| 		.variant = IMX95, | 		.variant = IMX95, | ||||||
| 		.flags = IMX_PCIE_FLAG_HAS_SERDES | | 		.flags = IMX_PCIE_FLAG_HAS_SERDES | | ||||||
| 			 IMX_PCIE_FLAG_HAS_LUT | | 			 IMX_PCIE_FLAG_HAS_LUT | | ||||||
|  | 			 IMX_PCIE_FLAG_8GT_ECN_ERR051586 | | ||||||
| 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | 			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND, | ||||||
| 		.ltssm_off = IMX95_PE0_GEN_CTRL_3, | 		.ltssm_off = IMX95_PE0_GEN_CTRL_3, | ||||||
| 		.ltssm_mask = IMX95_PCIE_LTSSM_EN, | 		.ltssm_mask = IMX95_PCIE_LTSSM_EN, | ||||||
| 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, | 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, | ||||||
| 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, | 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, | ||||||
|  | 		.core_reset = imx95_pcie_core_reset, | ||||||
| 		.init_phy = imx95_pcie_init_phy, | 		.init_phy = imx95_pcie_init_phy, | ||||||
|  | 		.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock, | ||||||
| 	}, | 	}, | ||||||
| 	[IMX8MQ_EP] = { | 	[IMX8MQ_EP] = { | ||||||
| 		.variant = IMX8MQ_EP, | 		.variant = IMX8MQ_EP, | ||||||
|  | @ -1799,12 +1947,15 @@ static const struct imx_pcie_drvdata drvdata[] = { | ||||||
| 	[IMX95_EP] = { | 	[IMX95_EP] = { | ||||||
| 		.variant = IMX95_EP, | 		.variant = IMX95_EP, | ||||||
| 		.flags = IMX_PCIE_FLAG_HAS_SERDES | | 		.flags = IMX_PCIE_FLAG_HAS_SERDES | | ||||||
|  | 			 IMX_PCIE_FLAG_8GT_ECN_ERR051586 | | ||||||
| 			 IMX_PCIE_FLAG_SUPPORT_64BIT, | 			 IMX_PCIE_FLAG_SUPPORT_64BIT, | ||||||
| 		.ltssm_off = IMX95_PE0_GEN_CTRL_3, | 		.ltssm_off = IMX95_PE0_GEN_CTRL_3, | ||||||
| 		.ltssm_mask = IMX95_PCIE_LTSSM_EN, | 		.ltssm_mask = IMX95_PCIE_LTSSM_EN, | ||||||
| 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, | 		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1, | ||||||
| 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, | 		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, | ||||||
| 		.init_phy = imx95_pcie_init_phy, | 		.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, | 		.epc_features = &imx95_pcie_epc_features, | ||||||
| 		.mode = DW_PCIE_EP_TYPE, | 		.mode = DW_PCIE_EP_TYPE, | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | @ -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 |  * @pci: A pointer to the dw_pcie structure which holds the DesignWare PCIe host | ||||||
|  *	 controller driver information. |  *	 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; | 	u32 val; | ||||||
| 
 | 
 | ||||||
| 	val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0); | 	val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0); | ||||||
| 	val &= PORT_LOGIC_LTSSM_STATE_MASK; | 	return (val & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L0; | ||||||
| 	return (val == PORT_LOGIC_LTSSM_STATE_L0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ks_pcie_stop_link(struct dw_pcie *pci) | static void ks_pcie_stop_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -335,7 +335,7 @@ static struct pci_ops meson_pci_ops = { | ||||||
| 	.write = pci_generic_config_write, | 	.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 meson_pcie *mp = to_meson_pcie(pci); | ||||||
| 	struct device *dev = pci->dev; | 	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"); | 			dev_dbg(dev, "speed_okay\n"); | ||||||
| 
 | 
 | ||||||
| 		if (smlh_up && rdlh_up && ltssm_up && speed_okay) | 		if (smlh_up && rdlh_up && ltssm_up && speed_okay) | ||||||
| 			return 1; | 			return true; | ||||||
| 
 | 
 | ||||||
| 		cnt++; | 		cnt++; | ||||||
| 
 | 
 | ||||||
|  | @ -371,7 +371,7 @@ static int meson_pcie_link_up(struct dw_pcie *pci) | ||||||
| 	} while (cnt < WAIT_LINKUP_TIMEOUT); | 	} while (cnt < WAIT_LINKUP_TIMEOUT); | ||||||
| 
 | 
 | ||||||
| 	dev_err(dev, "error: wait linkup timeout\n"); | 	dev_err(dev, "error: wait linkup timeout\n"); | ||||||
| 	return 0; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int meson_pcie_host_init(struct dw_pcie_rp *pp) | static int meson_pcie_host_init(struct dw_pcie_rp *pp) | ||||||
|  |  | ||||||
|  | @ -139,7 +139,7 @@ static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie) | ||||||
| 	return ret; | 	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 reg; | ||||||
| 	u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; | 	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); | 	reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG); | ||||||
| 
 | 
 | ||||||
| 	if ((reg & mask) == mask) | 	if ((reg & mask) == mask) | ||||||
| 		return 1; | 		return true; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg); | 	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) | static int armada8k_pcie_start_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -642,16 +642,262 @@ static void dwc_pcie_ltssm_debugfs_init(struct dw_pcie *pci, struct dentry *dir) | ||||||
| 			    &dwc_pcie_ltssm_status_ops); | 			    &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) | void dwc_pcie_debugfs_deinit(struct dw_pcie *pci) | ||||||
| { | { | ||||||
| 	if (!pci->debugfs) | 	if (!pci->debugfs) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | 	pcie_ptm_destroy_debugfs(pci->ptm_debugfs); | ||||||
| 	dwc_pcie_rasdes_debugfs_deinit(pci); | 	dwc_pcie_rasdes_debugfs_deinit(pci); | ||||||
| 	debugfs_remove_recursive(pci->debugfs->debug_dir); | 	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]; | 	char dirname[DWC_DEBUGFS_BUF_MAX]; | ||||||
| 	struct device *dev = pci->dev; | 	struct device *dev = pci->dev; | ||||||
|  | @ -674,4 +920,8 @@ void dwc_pcie_debugfs_init(struct dw_pcie *pci) | ||||||
| 			err); | 			err); | ||||||
| 
 | 
 | ||||||
| 	dwc_pcie_ltssm_debugfs_init(pci, dir); | 	dwc_pcie_ltssm_debugfs_init(pci, dir); | ||||||
|  | 
 | ||||||
|  | 	pci->mode = mode; | ||||||
|  | 	pci->ptm_debugfs = pcie_ptm_create_debugfs(pci->dev, pci, | ||||||
|  | 						   &dw_pcie_ptm_ops); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -256,11 +256,11 @@ static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci, | ||||||
| 		return offset; | 		return offset; | ||||||
| 
 | 
 | ||||||
| 	reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); | 	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) { | 	for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) { | ||||||
| 		reg = dw_pcie_readl_dbi(pci, 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) | 		if (bar_index == bar) | ||||||
| 			return offset; | 			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); | 	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, | 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_ep *ep = epc_get_drvdata(epc); | ||||||
| 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | ||||||
| 	struct dw_pcie_ep_func *ep_func; | 	struct dw_pcie_ep_func *ep_func; | ||||||
|  | 	u8 mmc = order_base_2(nr_irqs); | ||||||
| 	u32 val, reg; | 	u32 val, reg; | ||||||
| 
 | 
 | ||||||
| 	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); | 	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; | 	reg = ep_func->msi_cap + PCI_MSI_FLAGS; | ||||||
| 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg); | 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg); | ||||||
| 	val &= ~PCI_MSI_FLAGS_QMASK; | 	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_dbi_ro_wr_en(pci); | ||||||
| 	dw_pcie_ep_writew_dbi(ep, func_no, reg, val); | 	dw_pcie_ep_writew_dbi(ep, func_no, reg, val); | ||||||
| 	dw_pcie_dbi_ro_wr_dis(pci); | 	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; | 	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, | 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_ep *ep = epc_get_drvdata(epc); | ||||||
| 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 	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; | 	reg = ep_func->msix_cap + PCI_MSIX_FLAGS; | ||||||
| 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg); | 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg); | ||||||
| 	val &= ~PCI_MSIX_FLAGS_QSIZE; | 	val &= ~PCI_MSIX_FLAGS_QSIZE; | ||||||
| 	val |= interrupts; | 	val |= nr_irqs - 1; /* encoded as N-1 */ | ||||||
| 	dw_pcie_writew_dbi(pci, reg, val); | 	dw_pcie_writew_dbi(pci, reg, val); | ||||||
| 
 | 
 | ||||||
| 	reg = ep_func->msix_cap + PCI_MSIX_TABLE; | 	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); | 	dw_pcie_ep_writel_dbi(ep, func_no, reg, val); | ||||||
| 
 | 
 | ||||||
| 	reg = ep_func->msix_cap + PCI_MSIX_PBA; | 	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_ep_writel_dbi(ep, func_no, reg, val); | ||||||
| 
 | 
 | ||||||
| 	dw_pcie_dbi_ro_wr_dis(pci); | 	dw_pcie_dbi_ro_wr_dis(pci); | ||||||
|  | @ -671,7 +672,7 @@ static const struct pci_epc_ops epc_ops = { | ||||||
|  * @ep: DWC EP device |  * @ep: DWC EP device | ||||||
|  * @func_no: Function number of the endpoint |  * @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) | 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 |  * @func_no: Function number of the endpoint | ||||||
|  * @interrupt_num: Interrupt number to be raised |  * @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, | int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, | ||||||
| 			     u8 interrupt_num) | 			     u8 interrupt_num) | ||||||
|  | @ -875,8 +876,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) | ||||||
| 
 | 
 | ||||||
| 	if (offset) { | 	if (offset) { | ||||||
| 		reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); | 		reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); | ||||||
| 		nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> | 		nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg); | ||||||
| 			PCI_REBAR_CTRL_NBAR_SHIFT; |  | ||||||
| 
 | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * PCIe r6.0, sec 7.8.6.2 require us to support at least one | 		 * 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. | 			 * is why RESBAR_CAP_REG is written here. | ||||||
| 			 */ | 			 */ | ||||||
| 			val = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); | 			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]) | 			if (ep->epf_bar[bar]) | ||||||
| 				pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val); | 				pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val); | ||||||
| 			else | 			else | ||||||
|  | @ -1013,7 +1013,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) | ||||||
| 
 | 
 | ||||||
| 	dw_pcie_ep_init_non_sticky_registers(pci); | 	dw_pcie_ep_init_non_sticky_registers(pci); | ||||||
| 
 | 
 | ||||||
| 	dwc_pcie_debugfs_init(pci); | 	dwc_pcie_debugfs_init(pci, DW_PCIE_EP_TYPE); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -523,6 +523,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) | ||||||
| 
 | 
 | ||||||
| 	dw_pcie_iatu_detect(pci); | 	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 | 	 * Allocate the resource for MSG TLP before programming the iATU | ||||||
| 	 * outbound window in dw_pcie_setup_rc(). Since the allocation depends | 	 * 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) | 	if (pp->ops->post_init) | ||||||
| 		pp->ops->post_init(pp); | 		pp->ops->post_init(pp); | ||||||
| 
 | 
 | ||||||
| 	dwc_pcie_debugfs_init(pci); | 	dwc_pcie_debugfs_init(pci, DW_PCIE_RC_TYPE); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -828,6 +835,77 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) | ||||||
| 	return 0; | 	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) | int dw_pcie_setup_rc(struct dw_pcie_rp *pp) | ||||||
| { | { | ||||||
| 	struct dw_pcie *pci = to_dw_pcie_from_pp(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; | 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR; | ||||||
| 	dw_pcie_writel_dbi(pci, PCI_COMMAND, val); | 	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 | 	 * If the platform provides its own child bus config accesses, it means | ||||||
| 	 * the platform uses its own address translation component rather than | 	 * the platform uses its own address translation component rather than | ||||||
|  |  | ||||||
|  | @ -54,6 +54,14 @@ static const char * const dw_pcie_core_rsts[DW_PCIE_NUM_CORE_RSTS] = { | ||||||
| 	[DW_PCIE_PWR_RST] = "pwr", | 	[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) | static int dw_pcie_get_clocks(struct dw_pcie *pci) | ||||||
| { | { | ||||||
| 	int i, ret; | 	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); | 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) | int dw_pcie_read(void __iomem *addr, int size, u32 *val) | ||||||
| { | { | ||||||
| 	if (!IS_ALIGNED((uintptr_t)addr, size)) { | 	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); | 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; | 	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) | static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes) | ||||||
| { | { | ||||||
| 	u32 lnkcap, lwsc, plc; | 	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 */ | 	/* Set link width speed control register */ | ||||||
| 	lwsc = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); | 	lwsc = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); | ||||||
| 	lwsc &= ~PORT_LOGIC_LINK_WIDTH_MASK; | 	lwsc &= ~PORT_LOGIC_LINK_WIDTH_MASK; | ||||||
|  | 	lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES; | ||||||
| 	switch (num_lanes) { | 	switch (num_lanes) { | ||||||
| 	case 1: | 	case 1: | ||||||
| 		plc |= PORT_LINK_MODE_1_LANES; | 		plc |= PORT_LINK_MODE_1_LANES; | ||||||
| 		lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES; |  | ||||||
| 		break; | 		break; | ||||||
| 	case 2: | 	case 2: | ||||||
| 		plc |= PORT_LINK_MODE_2_LANES; | 		plc |= PORT_LINK_MODE_2_LANES; | ||||||
| 		lwsc |= PORT_LOGIC_LINK_WIDTH_2_LANES; |  | ||||||
| 		break; | 		break; | ||||||
| 	case 4: | 	case 4: | ||||||
| 		plc |= PORT_LINK_MODE_4_LANES; | 		plc |= PORT_LINK_MODE_4_LANES; | ||||||
| 		lwsc |= PORT_LOGIC_LINK_WIDTH_4_LANES; |  | ||||||
| 		break; | 		break; | ||||||
| 	case 8: | 	case 8: | ||||||
| 		plc |= PORT_LINK_MODE_8_LANES; | 		plc |= PORT_LINK_MODE_8_LANES; | ||||||
| 		lwsc |= PORT_LOGIC_LINK_WIDTH_8_LANES; |  | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		dev_err(pci->dev, "num-lanes %u: invalid value\n", num_lanes); | 		dev_err(pci->dev, "num-lanes %u: invalid value\n", num_lanes); | ||||||
|  |  | ||||||
|  | @ -25,6 +25,8 @@ | ||||||
| #include <linux/pci-epc.h> | #include <linux/pci-epc.h> | ||||||
| #include <linux/pci-epf.h> | #include <linux/pci-epf.h> | ||||||
| 
 | 
 | ||||||
|  | #include "../../pci.h" | ||||||
|  | 
 | ||||||
| /* DWC PCIe IP-core versions (native support since v4.70a) */ | /* DWC PCIe IP-core versions (native support since v4.70a) */ | ||||||
| #define DW_PCIE_VER_365A		0x3336352a | #define DW_PCIE_VER_365A		0x3336352a | ||||||
| #define DW_PCIE_VER_460A		0x3436302a | #define DW_PCIE_VER_460A		0x3436302a | ||||||
|  | @ -260,6 +262,21 @@ | ||||||
| 
 | 
 | ||||||
| #define PCIE_RAS_DES_EVENT_COUNTER_DATA		0xc | #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 |  * 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 |  * 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; | 	int			msg_atu_index; | ||||||
| 	struct resource		*msg_res; | 	struct resource		*msg_res; | ||||||
| 	bool			use_linkup_irq; | 	bool			use_linkup_irq; | ||||||
|  | 	struct pci_eq_presets	presets; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct dw_pcie_ep_ops { | struct dw_pcie_ep_ops { | ||||||
|  | @ -462,7 +480,7 @@ struct dw_pcie_ops { | ||||||
| 			     size_t size, u32 val); | 			     size_t size, u32 val); | ||||||
| 	void    (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg, | 	void    (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg, | ||||||
| 			      size_t size, u32 val); | 			      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); | 	enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie); | ||||||
| 	int	(*start_link)(struct dw_pcie *pcie); | 	int	(*start_link)(struct dw_pcie *pcie); | ||||||
| 	void	(*stop_link)(struct dw_pcie *pcie); | 	void	(*stop_link)(struct dw_pcie *pcie); | ||||||
|  | @ -503,6 +521,9 @@ struct dw_pcie { | ||||||
| 	struct gpio_desc		*pe_rst; | 	struct gpio_desc		*pe_rst; | ||||||
| 	bool			suspended; | 	bool			suspended; | ||||||
| 	struct debugfs_info	*debugfs; | 	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, | 	 * 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); | 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_ext_capability(struct dw_pcie *pci, u8 cap); | ||||||
| u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci); | 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_read(void __iomem *addr, int size, u32 *val); | ||||||
| int dw_pcie_write(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); | 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_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); | 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); | void dw_pcie_upconfig_setup(struct dw_pcie *pci); | ||||||
| int dw_pcie_wait_for_link(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, | int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, | ||||||
| 			      const struct dw_pcie_ob_atu_cfg *atu); | 			      const struct dw_pcie_ob_atu_cfg *atu); | ||||||
| int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type, | 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 | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_PCIE_DW_DEBUGFS | #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); | void dwc_pcie_debugfs_deinit(struct dw_pcie *pci); | ||||||
| #else | #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) | static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
|  * Author: Simon Xue <xxm@rock-chips.com> |  * Author: Simon Xue <xxm@rock-chips.com> | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <linux/bitfield.h> | ||||||
| #include <linux/clk.h> | #include <linux/clk.h> | ||||||
| #include <linux/gpio/consumer.h> | #include <linux/gpio/consumer.h> | ||||||
| #include <linux/irqchip/chained_irq.h> | #include <linux/irqchip/chained_irq.h> | ||||||
|  | @ -21,6 +22,7 @@ | ||||||
| #include <linux/regmap.h> | #include <linux/regmap.h> | ||||||
| #include <linux/reset.h> | #include <linux/reset.h> | ||||||
| 
 | 
 | ||||||
|  | #include "../../pci.h" | ||||||
| #include "pcie-designware.h" | #include "pcie-designware.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -33,25 +35,35 @@ | ||||||
| 
 | 
 | ||||||
| #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) | #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) | ||||||
| 
 | 
 | ||||||
|  | /* General Control Register */ | ||||||
|  | #define PCIE_CLIENT_GENERAL_CON		0x0 | ||||||
| #define  PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40) | #define  PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40) | ||||||
| #define  PCIE_CLIENT_EP_MODE		HIWORD_UPDATE(0xf0, 0x0) | #define  PCIE_CLIENT_EP_MODE		HIWORD_UPDATE(0xf0, 0x0) | ||||||
| #define  PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc) | #define  PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc) | ||||||
| #define  PCIE_CLIENT_DISABLE_LTSSM	HIWORD_UPDATE(0x0c, 0x8) | #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_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_RDLH_LINK_UP_CHGED	BIT(1) | ||||||
| #define  PCIE_LINK_REQ_RST_NOT_INT	BIT(2) | #define  PCIE_LINK_REQ_RST_NOT_INT	BIT(2) | ||||||
| #define PCIE_L0S_ENTRY			0x11 | 
 | ||||||
| #define PCIE_CLIENT_GENERAL_CONTROL	0x0 | /* Interrupt Mask Register Related to Legacy Interrupt */ | ||||||
| #define PCIE_CLIENT_INTR_STATUS_LEGACY	0x8 |  | ||||||
| #define PCIE_CLIENT_INTR_MASK_LEGACY	0x1c | #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_CLIENT_HOT_RESET_CTRL	0x180 | ||||||
| #define PCIE_CLIENT_LTSSM_STATUS	0x300 |  | ||||||
| #define  PCIE_LTSSM_ENABLE_ENHANCE	BIT(4) | #define  PCIE_LTSSM_ENABLE_ENHANCE	BIT(4) | ||||||
|  | 
 | ||||||
|  | /* LTSSM Status Register */ | ||||||
|  | #define PCIE_CLIENT_LTSSM_STATUS	0x300 | ||||||
|  | #define  PCIE_LINKUP			0x3 | ||||||
|  | #define  PCIE_LINKUP_MASK		GENMASK(17, 16) | ||||||
| #define  PCIE_LTSSM_STATUS_MASK		GENMASK(5, 0) | #define  PCIE_LTSSM_STATUS_MASK		GENMASK(5, 0) | ||||||
| 
 | 
 | ||||||
| struct rockchip_pcie { | struct rockchip_pcie { | ||||||
|  | @ -163,25 +175,36 @@ static u32 rockchip_pcie_get_ltssm(struct rockchip_pcie *rockchip) | ||||||
| static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip) | static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip) | ||||||
| { | { | ||||||
| 	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM, | 	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) | static void rockchip_pcie_disable_ltssm(struct rockchip_pcie *rockchip) | ||||||
| { | { | ||||||
| 	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DISABLE_LTSSM, | 	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); | 	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); | ||||||
| 	u32 val = rockchip_pcie_get_ltssm(rockchip); | 	u32 val = rockchip_pcie_get_ltssm(rockchip); | ||||||
| 
 | 
 | ||||||
| 	if ((val & PCIE_LINKUP) == PCIE_LINKUP && | 	return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP; | ||||||
| 	    (val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY) | } | ||||||
| 		return 1; |  | ||||||
| 
 | 
 | ||||||
| 	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) | 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 | 	 * 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. | 	 * 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); | 	gpiod_set_value_cansleep(rockchip->rst_gpio, 1); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	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, | 	irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler, | ||||||
| 					 rockchip); | 					 rockchip); | ||||||
| 
 | 
 | ||||||
|  | 	rockchip_pcie_enable_l0s(pci); | ||||||
|  | 
 | ||||||
| 	return 0; | 	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"); | 		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) | static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep) | ||||||
| { | { | ||||||
| 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | ||||||
| 	enum pci_barno bar; | 	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++) | 	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) | ||||||
| 		dw_pcie_ep_reset_bar(pci, 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 = { | static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = { | ||||||
| 	.init = rockchip_pcie_ep_init, | 	.init = rockchip_pcie_ep_init, | ||||||
| 	.pre_init = rockchip_pcie_ep_pre_init, |  | ||||||
| 	.raise_irq = rockchip_pcie_raise_irq, | 	.raise_irq = rockchip_pcie_raise_irq, | ||||||
| 	.get_features = rockchip_pcie_get_features, | 	.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) | static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip) | ||||||
| { | { | ||||||
| 	phy_exit(rockchip->phy); |  | ||||||
| 	phy_power_off(rockchip->phy); | 	phy_power_off(rockchip->phy); | ||||||
|  | 	phy_exit(rockchip->phy); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct dw_pcie_ops dw_pcie_ops = { | 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 *pci = &rockchip->pci; | ||||||
| 	struct dw_pcie_rp *pp = &pci->pp; | 	struct dw_pcie_rp *pp = &pci->pp; | ||||||
| 	struct device *dev = pci->dev; | 	struct device *dev = pci->dev; | ||||||
| 	u32 reg, val; | 	u32 reg; | ||||||
| 
 | 
 | ||||||
| 	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); | 	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); | ||||||
| 	rockchip_pcie_writel_apb(rockchip, reg, 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)); | 	dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip)); | ||||||
| 
 | 
 | ||||||
| 	if (reg & PCIE_RDLH_LINK_UP_CHGED) { | 	if (reg & PCIE_RDLH_LINK_UP_CHGED) { | ||||||
| 		val = rockchip_pcie_get_ltssm(rockchip); | 		if (rockchip_pcie_link_up(pci)) { | ||||||
| 		if ((val & PCIE_LINKUP) == PCIE_LINKUP) { |  | ||||||
| 			dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); | 			dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); | ||||||
| 			/* Rescan the bus to enumerate endpoint devices */ | 			/* Rescan the bus to enumerate endpoint devices */ | ||||||
| 			pci_lock_rescan_remove(); | 			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 rockchip_pcie *rockchip = arg; | ||||||
| 	struct dw_pcie *pci = &rockchip->pci; | 	struct dw_pcie *pci = &rockchip->pci; | ||||||
| 	struct device *dev = pci->dev; | 	struct device *dev = pci->dev; | ||||||
| 	u32 reg, val; | 	u32 reg; | ||||||
| 
 | 
 | ||||||
| 	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); | 	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); | ||||||
| 	rockchip_pcie_writel_apb(rockchip, reg, 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) { | 	if (reg & PCIE_RDLH_LINK_UP_CHGED) { | ||||||
| 		val = rockchip_pcie_get_ltssm(rockchip); | 		if (rockchip_pcie_link_up(pci)) { | ||||||
| 		if ((val & PCIE_LINKUP) == PCIE_LINKUP) { |  | ||||||
| 			dev_dbg(dev, "link up\n"); | 			dev_dbg(dev, "link up\n"); | ||||||
| 			dw_pcie_ep_linkup(&pci->ep); | 			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, val, PCIE_CLIENT_HOT_RESET_CTRL); | ||||||
| 
 | 
 | ||||||
| 	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, | 	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, | ||||||
| 				 PCIE_CLIENT_GENERAL_CONTROL); | 				 PCIE_CLIENT_GENERAL_CON); | ||||||
| 
 | 
 | ||||||
| 	pp = &rockchip->pci.pp; | 	pp = &rockchip->pci.pp; | ||||||
| 	pp->ops = &rockchip_pcie_host_ops; | 	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, val, PCIE_CLIENT_HOT_RESET_CTRL); | ||||||
| 
 | 
 | ||||||
| 	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE, | 	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.ops = &rockchip_pcie_ep_ops; | ||||||
| 	rockchip->pci.ep.page_size = SZ_64K; | 	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->pci.ops = &dw_pcie_ops; | ||||||
| 	rockchip->data = data; | 	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); | 	ret = rockchip_pcie_resource_get(pdev, rockchip); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ | ||||||
| #include <linux/pci-acpi.h> | #include <linux/pci-acpi.h> | ||||||
| #include <linux/pci-ecam.h> | #include <linux/pci-ecam.h> | ||||||
| #include "../../pci.h" | #include "../../pci.h" | ||||||
|  | #include "../pci-host-common.h" | ||||||
| 
 | 
 | ||||||
| #if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | #if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -151,7 +151,7 @@ static struct pci_ops histb_pci_ops = { | ||||||
| 	.write = histb_pcie_wr_own_conf, | 	.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); | 	struct histb_pcie *hipcie = to_histb_pcie(pci); | ||||||
| 	u32 regval; | 	u32 regval; | ||||||
|  | @ -160,11 +160,8 @@ static int histb_pcie_link_up(struct dw_pcie *pci) | ||||||
| 	regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0); | 	regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0); | ||||||
| 	status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4); | 	status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4); | ||||||
| 	status &= PCIE_LTSSM_STATE_MASK; | 	status &= PCIE_LTSSM_STATE_MASK; | ||||||
| 	if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) && | 	return ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) && | ||||||
| 	    (status == PCIE_LTSSM_STATE_ACTIVE)) | 		(status == PCIE_LTSSM_STATE_ACTIVE)); | ||||||
| 		return 1; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int histb_pcie_start_link(struct dw_pcie *pci) | static int histb_pcie_start_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -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); | 	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); | 	struct keembay_pcie *pcie = dev_get_drvdata(pci->dev); | ||||||
| 	u32 val; | 	u32 val; | ||||||
|  |  | ||||||
|  | @ -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); | 	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); | 	struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); | ||||||
| 	u32 val; | 	u32 val; | ||||||
| 
 | 
 | ||||||
| 	regmap_read(kirin_pcie->apb, PCIE_APB_PHY_STATUS0, &val); | 	regmap_read(kirin_pcie->apb, PCIE_APB_PHY_STATUS0, &val); | ||||||
| 	if ((val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE) | 	return (val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE; | ||||||
| 		return 1; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int kirin_pcie_start_link(struct dw_pcie *pci) | static int kirin_pcie_start_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ | ||||||
| #define PARF_DEVICE_TYPE			0x1000 | #define PARF_DEVICE_TYPE			0x1000 | ||||||
| #define PARF_BDF_TO_SID_CFG			0x2c00 | #define PARF_BDF_TO_SID_CFG			0x2c00 | ||||||
| #define PARF_INT_ALL_5_MASK			0x2dcc | #define PARF_INT_ALL_5_MASK			0x2dcc | ||||||
|  | #define PARF_INT_ALL_3_MASK			0x2e18 | ||||||
| 
 | 
 | ||||||
| /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ | /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ | ||||||
| #define PARF_INT_ALL_LINK_DOWN			BIT(1) | #define PARF_INT_ALL_LINK_DOWN			BIT(1) | ||||||
|  | @ -132,6 +133,9 @@ | ||||||
| /* PARF_INT_ALL_5_MASK fields */ | /* PARF_INT_ALL_5_MASK fields */ | ||||||
| #define PARF_INT_ALL_5_MHI_RAM_DATA_PARITY_ERR	BIT(0) | #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 */ | /* ELBI registers */ | ||||||
| #define ELBI_SYS_STTS				0x08 | #define ELBI_SYS_STTS				0x08 | ||||||
| #define ELBI_CS2_ENABLE				0xa4 | #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); | 	struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci); | ||||||
| 	u32 reg; | 	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); | 		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); | 	ret = dw_pcie_ep_init_registers(&pcie_ep->pci.ep); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		dev_err(dev, "Failed to complete initialization: %d\n", ret); | 		dev_err(dev, "Failed to complete initialization: %d\n", ret); | ||||||
|  |  | ||||||
|  | @ -289,7 +289,7 @@ static void qcom_ep_reset_assert(struct qcom_pcie *pcie) | ||||||
| static void qcom_ep_reset_deassert(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 */ | 	/* 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); | 	gpiod_set_value_cansleep(pcie->reset, 0); | ||||||
| 	usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); | 	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; | 	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 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); | ||||||
| 	u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA); | 	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) | 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-apq8064", .data = &cfg_2_1_0 }, | ||||||
| 	{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 }, | 	{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 }, | ||||||
| 	{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_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-ipq6018", .data = &cfg_2_9_0 }, | ||||||
| 	{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 }, | 	{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 }, | ||||||
| 	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 }, | 	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 }, | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ struct rcar_gen4_pcie { | ||||||
| #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw) | #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw) | ||||||
| 
 | 
 | ||||||
| /* Common */ | /* 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); | 	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); | ||||||
| 	u32 val, mask; | 	u32 val, mask; | ||||||
|  | @ -403,6 +403,7 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = { | ||||||
| 	.msix_capable = false, | 	.msix_capable = false, | ||||||
| 	.bar[BAR_1] = { .type = BAR_RESERVED, }, | 	.bar[BAR_1] = { .type = BAR_RESERVED, }, | ||||||
| 	.bar[BAR_3] = { .type = BAR_RESERVED, }, | 	.bar[BAR_3] = { .type = BAR_RESERVED, }, | ||||||
|  | 	.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256 }, | ||||||
| 	.bar[BAR_5] = { .type = BAR_RESERVED, }, | 	.bar[BAR_5] = { .type = BAR_RESERVED, }, | ||||||
| 	.align = SZ_1M, | 	.align = SZ_1M, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -110,15 +110,12 @@ static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pc | ||||||
| 				MSI_CTRL_INT, &app_reg->int_mask); | 				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 spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); | ||||||
| 	struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; | 	struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; | ||||||
| 
 | 
 | ||||||
| 	if (readl(&app_reg->app_status_1) & XMLH_LINK_UP) | 	return readl(&app_reg->app_status_1) & XMLH_LINK_UP; | ||||||
| 		return 1; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp) | static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp) | ||||||
|  |  | ||||||
|  | @ -713,7 +713,16 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie) | ||||||
| 
 | 
 | ||||||
| static void init_debugfs(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); | 				    aspm_state_cnt); | ||||||
| } | } | ||||||
| #else | #else | ||||||
|  | @ -1027,12 +1036,12 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci) | ||||||
| 	return 0; | 	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); | 	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); | ||||||
| 	u32 val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA); | 	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) | 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) | static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) | ||||||
| { | { | ||||||
| 	struct device *dev = pcie->dev; | 	struct device *dev = pcie->dev; | ||||||
| 	char *name; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	pm_runtime_enable(dev); | 	pm_runtime_enable(dev); | ||||||
|  | @ -1664,13 +1672,6 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) | ||||||
| 		goto fail_host_init; | 		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); | 	init_debugfs(pcie); | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ static int uniphier_pcie_wait_rc(struct uniphier_pcie *pcie) | ||||||
| 	return 0; | 	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); | 	struct uniphier_pcie *pcie = to_uniphier_pcie(pci); | ||||||
| 	u32 val, mask; | 	u32 val, mask; | ||||||
|  |  | ||||||
|  | @ -121,13 +121,13 @@ static u32 visconti_mpu_readl(struct visconti_pcie *pcie, u32 reg) | ||||||
| 	return readl_relaxed(pcie->mpu_base + 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); | 	struct visconti_pcie *pcie = dev_get_drvdata(pci->dev); | ||||||
| 	void __iomem *addr = pcie->ulreg_base; | 	void __iomem *addr = pcie->ulreg_base; | ||||||
| 	u32 val = readl_relaxed(addr + PCIE_UL_REG_V_PHY_ST_02); | 	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) | static int visconti_pcie_start_link(struct dw_pcie *pci) | ||||||
|  |  | ||||||
|  | @ -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); | 	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); | 	struct ls_g4_pcie *pcie = to_ls_g4_pcie(pci); | ||||||
| 	u32 state; | 	u32 state; | ||||||
| 
 | 
 | ||||||
| 	state = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG); | 	state = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG); | ||||||
| 	state =	state & PF_DBG_LTSSM_MASK; | 	return (state & PF_DBG_LTSSM_MASK) == PF_DBG_LTSSM_L0; | ||||||
| 
 |  | ||||||
| 	if (state == PF_DBG_LTSSM_L0) |  | ||||||
| 		return 1; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ls_g4_pcie_disable_interrupt(struct ls_g4_pcie *pcie) | 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) | static void ls_g4_pcie_reset(struct work_struct *work) | ||||||
| { | { | ||||||
| 	struct delayed_work *dwork = container_of(work, struct delayed_work, | 	struct delayed_work *dwork = to_delayed_work(work); | ||||||
| 						  work); |  | ||||||
| 	struct ls_g4_pcie *pcie = container_of(dwork, struct ls_g4_pcie, dwork); | 	struct ls_g4_pcie *pcie = container_of(dwork, struct ls_g4_pcie, dwork); | ||||||
| 	struct mobiveil_pcie *mv_pci = &pcie->pci; | 	struct mobiveil_pcie *mv_pci = &pcie->pci; | ||||||
| 	u16 ctrl; | 	u16 ctrl; | ||||||
|  |  | ||||||
|  | @ -160,7 +160,7 @@ struct mobiveil_root_port { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct mobiveil_pab_ops { | struct mobiveil_pab_ops { | ||||||
| 	int (*link_up)(struct mobiveil_pcie *pcie); | 	bool (*link_up)(struct mobiveil_pcie *pcie); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct mobiveil_pcie { | struct mobiveil_pcie { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| // SPDX-License-Identifier: GPL-2.0
 | // SPDX-License-Identifier: GPL-2.0
 | ||||||
| /*
 | /*
 | ||||||
|  * Generic PCI host driver common code |  * Common library for PCI host controller drivers | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2014 ARM Limited |  * Copyright (C) 2014 ARM Limited | ||||||
|  * |  * | ||||||
|  | @ -15,6 +15,8 @@ | ||||||
| #include <linux/pci-ecam.h> | #include <linux/pci-ecam.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| 
 | 
 | ||||||
|  | #include "pci-host-common.h" | ||||||
|  | 
 | ||||||
| static void gen_pci_unmap_cfg(void *ptr) | static void gen_pci_unmap_cfg(void *ptr) | ||||||
| { | { | ||||||
| 	pci_ecam_free((struct pci_config_window *)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; | 	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 device *dev = &pdev->dev; | ||||||
| 	struct pci_host_bridge *bridge; | 	struct pci_host_bridge *bridge; | ||||||
| 	struct pci_config_window *cfg; | 	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); | 	bridge = devm_pci_alloc_host_bridge(dev, 0); | ||||||
| 	if (!bridge) | 	if (!bridge) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	platform_set_drvdata(pdev, bridge); |  | ||||||
| 
 |  | ||||||
| 	of_pci_check_probe_only(); | 	of_pci_check_probe_only(); | ||||||
| 
 | 
 | ||||||
| 	/* Parse and map our Configuration Space windows */ | 	/* Parse and map our Configuration Space windows */ | ||||||
|  | @ -73,6 +69,8 @@ int pci_host_common_probe(struct platform_device *pdev) | ||||||
| 	if (IS_ERR(cfg)) | 	if (IS_ERR(cfg)) | ||||||
| 		return PTR_ERR(cfg); | 		return PTR_ERR(cfg); | ||||||
| 
 | 
 | ||||||
|  | 	platform_set_drvdata(pdev, bridge); | ||||||
|  | 
 | ||||||
| 	bridge->sysdata = cfg; | 	bridge->sysdata = cfg; | ||||||
| 	bridge->ops = (struct pci_ops *)&ops->pci_ops; | 	bridge->ops = (struct pci_ops *)&ops->pci_ops; | ||||||
| 	bridge->enable_device = ops->enable_device; | 	bridge->enable_device = ops->enable_device; | ||||||
|  | @ -81,6 +79,18 @@ int pci_host_common_probe(struct platform_device *pdev) | ||||||
| 
 | 
 | ||||||
| 	return pci_host_probe(bridge); | 	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); | EXPORT_SYMBOL_GPL(pci_host_common_probe); | ||||||
| 
 | 
 | ||||||
| void pci_host_common_remove(struct platform_device *pdev) | 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); | 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"); | MODULE_LICENSE("GPL v2"); | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								drivers/pci/controller/pci-host-common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								drivers/pci/controller/pci-host-common.h
									
									
									
									
									
										Normal 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 | ||||||
|  | @ -14,6 +14,8 @@ | ||||||
| #include <linux/pci-ecam.h> | #include <linux/pci-ecam.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| 
 | 
 | ||||||
|  | #include "pci-host-common.h" | ||||||
|  | 
 | ||||||
| static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = { | static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = { | ||||||
| 	.bus_shift	= 16, | 	.bus_shift	= 16, | ||||||
| 	.pci_ops	= { | 	.pci_ops	= { | ||||||
|  |  | ||||||
|  | @ -1179,37 +1179,29 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | ||||||
| 			      unsigned int *tgt, | 			      unsigned int *tgt, | ||||||
| 			      unsigned int *attr) | 			      unsigned int *attr) | ||||||
| { | { | ||||||
| 	const int na = 3, ns = 2; | 	struct of_range range; | ||||||
| 	const __be32 *range; | 	struct of_range_parser parser; | ||||||
| 	int rlen, nranges, rangesz, pna, i; |  | ||||||
| 
 | 
 | ||||||
| 	*tgt = -1; | 	*tgt = -1; | ||||||
| 	*attr = -1; | 	*attr = -1; | ||||||
| 
 | 
 | ||||||
| 	range = of_get_property(np, "ranges", &rlen); | 	if (of_pci_range_parser_init(&parser, np)) | ||||||
| 	if (!range) |  | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	pna = of_n_addr_cells(np); | 	for_each_of_range(&parser, &range) { | ||||||
| 	rangesz = pna + na + ns; |  | ||||||
| 	nranges = rlen / sizeof(__be32) / rangesz; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < nranges; i++, range += rangesz) { |  | ||||||
| 		u32 flags = of_read_number(range, 1); |  | ||||||
| 		u32 slot = of_read_number(range + 1, 1); |  | ||||||
| 		u64 cpuaddr = of_read_number(range + na, pna); |  | ||||||
| 		unsigned long rtype; | 		unsigned long rtype; | ||||||
|  | 		u32 slot = upper_32_bits(range.bus_addr); | ||||||
| 
 | 
 | ||||||
| 		if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO) | 		if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_IO) | ||||||
| 			rtype = IORESOURCE_IO; | 			rtype = IORESOURCE_IO; | ||||||
| 		else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) | 		else if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_MEM32) | ||||||
| 			rtype = IORESOURCE_MEM; | 			rtype = IORESOURCE_MEM; | ||||||
| 		else | 		else | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		if (slot == PCI_SLOT(devfn) && type == rtype) { | 		if (slot == PCI_SLOT(devfn) && type == rtype) { | ||||||
| 			*tgt = DT_CPUADDR_TO_TARGET(cpuaddr); | 			*tgt = DT_CPUADDR_TO_TARGET(range.cpu_addr); | ||||||
| 			*attr = DT_CPUADDR_TO_ATTR(cpuaddr); | 			*attr = DT_CPUADDR_TO_ATTR(range.cpu_addr); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ | ||||||
| #include <linux/pci-ecam.h> | #include <linux/pci-ecam.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| 
 | 
 | ||||||
|  | #include "pci-host-common.h" | ||||||
|  | 
 | ||||||
| #if defined(CONFIG_PCI_HOST_THUNDER_ECAM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | #if defined(CONFIG_PCI_HOST_THUNDER_ECAM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | ||||||
| 
 | 
 | ||||||
| static void set_val(u32 v, int where, int size, u32 *val) | static void set_val(u32 v, int where, int size, u32 *val) | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| #include <linux/io-64-nonatomic-lo-hi.h> | #include <linux/io-64-nonatomic-lo-hi.h> | ||||||
| #include "../pci.h" | #include "../pci.h" | ||||||
|  | #include "pci-host-common.h" | ||||||
| 
 | 
 | ||||||
| #if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | #if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ | ||||||
|  * Author: Marc Zyngier <maz@kernel.org> |  * Author: Marc Zyngier <maz@kernel.org> | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <linux/bitfield.h> | ||||||
| #include <linux/gpio/consumer.h> | #include <linux/gpio/consumer.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/iopoll.h> | #include <linux/iopoll.h> | ||||||
|  | @ -30,6 +31,9 @@ | ||||||
| #include <linux/of_irq.h> | #include <linux/of_irq.h> | ||||||
| #include <linux/pci-ecam.h> | #include <linux/pci-ecam.h> | ||||||
| 
 | 
 | ||||||
|  | #include "pci-host-common.h" | ||||||
|  | 
 | ||||||
|  | /* T8103 (original M1) and related SoCs */ | ||||||
| #define CORE_RC_PHYIF_CTL		0x00024 | #define CORE_RC_PHYIF_CTL		0x00024 | ||||||
| #define   CORE_RC_PHYIF_CTL_RUN		BIT(0) | #define   CORE_RC_PHYIF_CTL_RUN		BIT(0) | ||||||
| #define CORE_RC_PHYIF_STAT		0x00028 | #define CORE_RC_PHYIF_STAT		0x00028 | ||||||
|  | @ -40,14 +44,18 @@ | ||||||
| #define   CORE_RC_STAT_READY		BIT(0) | #define   CORE_RC_STAT_READY		BIT(0) | ||||||
| #define CORE_FABRIC_STAT		0x04000 | #define CORE_FABRIC_STAT		0x04000 | ||||||
| #define   CORE_FABRIC_STAT_MASK		0x001F001F | #define   CORE_FABRIC_STAT_MASK		0x001F001F | ||||||
| #define CORE_LANE_CFG(port)		(0x84000 + 0x4000 * (port)) | 
 | ||||||
| #define   CORE_LANE_CFG_REFCLK0REQ	BIT(0) | #define CORE_PHY_DEFAULT_BASE(port)	(0x84000 + 0x4000 * (port)) | ||||||
| #define   CORE_LANE_CFG_REFCLK1REQ	BIT(1) | 
 | ||||||
| #define   CORE_LANE_CFG_REFCLK0ACK	BIT(2) | #define PHY_LANE_CFG			0x00000 | ||||||
| #define   CORE_LANE_CFG_REFCLK1ACK	BIT(3) | #define   PHY_LANE_CFG_REFCLK0REQ	BIT(0) | ||||||
| #define   CORE_LANE_CFG_REFCLKEN	(BIT(9) | BIT(10)) | #define   PHY_LANE_CFG_REFCLK1REQ	BIT(1) | ||||||
| #define CORE_LANE_CTL(port)		(0x84004 + 0x4000 * (port)) | #define   PHY_LANE_CFG_REFCLK0ACK	BIT(2) | ||||||
| #define   CORE_LANE_CTL_CFGACC		BIT(15) | #define   PHY_LANE_CFG_REFCLK1ACK	BIT(3) | ||||||
|  | #define   PHY_LANE_CFG_REFCLKEN		(BIT(9) | BIT(10)) | ||||||
|  | #define   PHY_LANE_CFG_REFCLKCGEN	(BIT(30) | BIT(31)) | ||||||
|  | #define PHY_LANE_CTL			0x00004 | ||||||
|  | #define   PHY_LANE_CTL_CFGACC		BIT(15) | ||||||
| 
 | 
 | ||||||
| #define PORT_LTSSMCTL			0x00080 | #define PORT_LTSSMCTL			0x00080 | ||||||
| #define   PORT_LTSSMCTL_START		BIT(0) | #define   PORT_LTSSMCTL_START		BIT(0) | ||||||
|  | @ -101,7 +109,7 @@ | ||||||
| #define   PORT_REFCLK_CGDIS		BIT(8) | #define   PORT_REFCLK_CGDIS		BIT(8) | ||||||
| #define PORT_PERST			0x00814 | #define PORT_PERST			0x00814 | ||||||
| #define   PORT_PERST_OFF		BIT(0) | #define   PORT_PERST_OFF		BIT(0) | ||||||
| #define PORT_RID2SID(i16)		(0x00828 + 4 * (i16)) | #define PORT_RID2SID			0x00828 | ||||||
| #define   PORT_RID2SID_VALID		BIT(31) | #define   PORT_RID2SID_VALID		BIT(31) | ||||||
| #define   PORT_RID2SID_SID_SHIFT	16 | #define   PORT_RID2SID_SID_SHIFT	16 | ||||||
| #define   PORT_RID2SID_BUS_SHIFT	8 | #define   PORT_RID2SID_BUS_SHIFT	8 | ||||||
|  | @ -119,7 +127,15 @@ | ||||||
| #define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1) | #define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1) | ||||||
| #define PORT_PREFMEM_ENABLE		0x00994 | #define PORT_PREFMEM_ENABLE		0x00994 | ||||||
| 
 | 
 | ||||||
| #define MAX_RID2SID			64 | /* T602x (M2-pro and co) */ | ||||||
|  | #define PORT_T602X_MSIADDR	0x016c | ||||||
|  | #define PORT_T602X_MSIADDR_HI	0x0170 | ||||||
|  | #define PORT_T602X_PERST	0x082c | ||||||
|  | #define PORT_T602X_RID2SID	0x3000 | ||||||
|  | #define PORT_T602X_MSIMAP	0x3800 | ||||||
|  | 
 | ||||||
|  | #define PORT_MSIMAP_ENABLE	BIT(31) | ||||||
|  | #define PORT_MSIMAP_TARGET	GENMASK(7, 0) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * The doorbell address is set to 0xfffff000, which by convention |  * The doorbell address is set to 0xfffff000, which by convention | ||||||
|  | @ -130,10 +146,45 @@ | ||||||
|  */ |  */ | ||||||
| #define DOORBELL_ADDR		CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR | #define DOORBELL_ADDR		CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR | ||||||
| 
 | 
 | ||||||
|  | struct hw_info { | ||||||
|  | 	u32 phy_lane_ctl; | ||||||
|  | 	u32 port_msiaddr; | ||||||
|  | 	u32 port_msiaddr_hi; | ||||||
|  | 	u32 port_refclk; | ||||||
|  | 	u32 port_perst; | ||||||
|  | 	u32 port_rid2sid; | ||||||
|  | 	u32 port_msimap; | ||||||
|  | 	u32 max_rid2sid; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct hw_info t8103_hw = { | ||||||
|  | 	.phy_lane_ctl		= PHY_LANE_CTL, | ||||||
|  | 	.port_msiaddr		= PORT_MSIADDR, | ||||||
|  | 	.port_msiaddr_hi	= 0, | ||||||
|  | 	.port_refclk		= PORT_REFCLK, | ||||||
|  | 	.port_perst		= PORT_PERST, | ||||||
|  | 	.port_rid2sid		= PORT_RID2SID, | ||||||
|  | 	.port_msimap		= 0, | ||||||
|  | 	.max_rid2sid		= 64, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct hw_info t602x_hw = { | ||||||
|  | 	.phy_lane_ctl		= 0, | ||||||
|  | 	.port_msiaddr		= PORT_T602X_MSIADDR, | ||||||
|  | 	.port_msiaddr_hi	= PORT_T602X_MSIADDR_HI, | ||||||
|  | 	.port_refclk		= 0, | ||||||
|  | 	.port_perst		= PORT_T602X_PERST, | ||||||
|  | 	.port_rid2sid		= PORT_T602X_RID2SID, | ||||||
|  | 	.port_msimap		= PORT_T602X_MSIMAP, | ||||||
|  | 	/* 16 on t602x, guess for autodetect on future HW */ | ||||||
|  | 	.max_rid2sid		= 512, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct apple_pcie { | struct apple_pcie { | ||||||
| 	struct mutex		lock; | 	struct mutex		lock; | ||||||
| 	struct device		*dev; | 	struct device		*dev; | ||||||
| 	void __iomem            *base; | 	void __iomem            *base; | ||||||
|  | 	const struct hw_info	*hw; | ||||||
| 	unsigned long		*bitmap; | 	unsigned long		*bitmap; | ||||||
| 	struct list_head	ports; | 	struct list_head	ports; | ||||||
| 	struct completion	event; | 	struct completion	event; | ||||||
|  | @ -142,12 +193,14 @@ struct apple_pcie { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct apple_pcie_port { | struct apple_pcie_port { | ||||||
|  | 	raw_spinlock_t		lock; | ||||||
| 	struct apple_pcie	*pcie; | 	struct apple_pcie	*pcie; | ||||||
| 	struct device_node	*np; | 	struct device_node	*np; | ||||||
| 	void __iomem		*base; | 	void __iomem		*base; | ||||||
|  | 	void __iomem		*phy; | ||||||
| 	struct irq_domain	*domain; | 	struct irq_domain	*domain; | ||||||
| 	struct list_head	entry; | 	struct list_head	entry; | ||||||
| 	DECLARE_BITMAP(sid_map, MAX_RID2SID); | 	unsigned long		*sid_map; | ||||||
| 	int			sid_map_sz; | 	int			sid_map_sz; | ||||||
| 	int			idx; | 	int			idx; | ||||||
| }; | }; | ||||||
|  | @ -233,14 +286,16 @@ static void apple_port_irq_mask(struct irq_data *data) | ||||||
| { | { | ||||||
| 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); | 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); | ||||||
| 
 | 
 | ||||||
| 	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKSET); | 	guard(raw_spinlock_irqsave)(&port->lock); | ||||||
|  | 	rmw_set(BIT(data->hwirq), port->base + PORT_INTMSK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void apple_port_irq_unmask(struct irq_data *data) | static void apple_port_irq_unmask(struct irq_data *data) | ||||||
| { | { | ||||||
| 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); | 	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data); | ||||||
| 
 | 
 | ||||||
| 	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKCLR); | 	guard(raw_spinlock_irqsave)(&port->lock); | ||||||
|  | 	rmw_clear(BIT(data->hwirq), port->base + PORT_INTMSK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool hwirq_is_intx(unsigned int hwirq) | static bool hwirq_is_intx(unsigned int hwirq) | ||||||
|  | @ -344,7 +399,9 @@ static void apple_port_irq_handler(struct irq_desc *desc) | ||||||
| static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) | static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) | ||||||
| { | { | ||||||
| 	struct fwnode_handle *fwnode = &port->np->fwnode; | 	struct fwnode_handle *fwnode = &port->np->fwnode; | ||||||
|  | 	struct apple_pcie *pcie = port->pcie; | ||||||
| 	unsigned int irq; | 	unsigned int irq; | ||||||
|  | 	u32 val = 0; | ||||||
| 
 | 
 | ||||||
| 	/* FIXME: consider moving each interrupt under each port */ | 	/* FIXME: consider moving each interrupt under each port */ | ||||||
| 	irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)), | 	irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)), | ||||||
|  | @ -359,20 +416,31 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	/* Disable all interrupts */ | 	/* Disable all interrupts */ | ||||||
| 	writel_relaxed(~0, port->base + PORT_INTMSKSET); | 	writel_relaxed(~0, port->base + PORT_INTMSK); | ||||||
| 	writel_relaxed(~0, port->base + PORT_INTSTAT); | 	writel_relaxed(~0, port->base + PORT_INTSTAT); | ||||||
|  | 	writel_relaxed(~0, port->base + PORT_LINKCMDSTS); | ||||||
| 
 | 
 | ||||||
| 	irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port); | 	irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port); | ||||||
| 
 | 
 | ||||||
| 	/* Configure MSI base address */ | 	/* Configure MSI base address */ | ||||||
| 	BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR)); | 	BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR)); | ||||||
| 	writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR); | 	writel_relaxed(lower_32_bits(DOORBELL_ADDR), | ||||||
|  | 		       port->base + pcie->hw->port_msiaddr); | ||||||
|  | 	if (pcie->hw->port_msiaddr_hi) | ||||||
|  | 		writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi); | ||||||
| 
 | 
 | ||||||
| 	/* Enable MSIs, shared between all ports */ | 	/* Enable MSIs, shared between all ports */ | ||||||
|  | 	if (pcie->hw->port_msimap) { | ||||||
|  | 		for (int i = 0; i < pcie->nvecs; i++) | ||||||
|  | 			writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) | | ||||||
|  | 				       PORT_MSIMAP_ENABLE, | ||||||
|  | 				       port->base + pcie->hw->port_msimap + 4 * i); | ||||||
|  | 	} else { | ||||||
| 		writel_relaxed(0, port->base + PORT_MSIBASE); | 		writel_relaxed(0, port->base + PORT_MSIBASE); | ||||||
| 	writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) | | 		val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT; | ||||||
| 		       PORT_MSICFG_EN, port->base + PORT_MSICFG); | 	} | ||||||
| 
 | 
 | ||||||
|  | 	writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -439,43 +507,47 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie, | ||||||
| 	u32 stat; | 	u32 stat; | ||||||
| 	int res; | 	int res; | ||||||
| 
 | 
 | ||||||
| 	res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat, | 	if (pcie->hw->phy_lane_ctl) | ||||||
| 					 stat & CORE_RC_PHYIF_STAT_REFCLK, | 		rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl); | ||||||
|  | 
 | ||||||
|  | 	rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG); | ||||||
|  | 
 | ||||||
|  | 	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG, | ||||||
|  | 					 stat, stat & PHY_LANE_CFG_REFCLK0ACK, | ||||||
| 					 100, 50000); | 					 100, 50000); | ||||||
| 	if (res < 0) | 	if (res < 0) | ||||||
| 		return res; | 		return res; | ||||||
| 
 | 
 | ||||||
| 	rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); | 	rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG); | ||||||
| 	rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx)); | 	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG, | ||||||
| 
 | 					 stat, stat & PHY_LANE_CFG_REFCLK1ACK, | ||||||
| 	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), |  | ||||||
| 					 stat, stat & CORE_LANE_CFG_REFCLK0ACK, |  | ||||||
| 					 100, 50000); |  | ||||||
| 	if (res < 0) |  | ||||||
| 		return res; |  | ||||||
| 
 |  | ||||||
| 	rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx)); |  | ||||||
| 	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), |  | ||||||
| 					 stat, stat & CORE_LANE_CFG_REFCLK1ACK, |  | ||||||
| 					 100, 50000); | 					 100, 50000); | ||||||
| 
 | 
 | ||||||
| 	if (res < 0) | 	if (res < 0) | ||||||
| 		return res; | 		return res; | ||||||
| 
 | 
 | ||||||
| 	rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); | 	if (pcie->hw->phy_lane_ctl) | ||||||
|  | 		rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl); | ||||||
| 
 | 
 | ||||||
| 	rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx)); | 	rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG); | ||||||
| 	rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK); | 
 | ||||||
|  | 	if (pcie->hw->port_refclk) | ||||||
|  | 		rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void __iomem *port_rid2sid_addr(struct apple_pcie_port *port, int idx) | ||||||
|  | { | ||||||
|  | 	return port->base + port->pcie->hw->port_rid2sid + 4 * idx; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port, | static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port, | ||||||
| 				    int idx, u32 val) | 				    int idx, u32 val) | ||||||
| { | { | ||||||
| 	writel_relaxed(val, port->base + PORT_RID2SID(idx)); | 	writel_relaxed(val, port_rid2sid_addr(port, idx)); | ||||||
| 	/* Read back to ensure completion of the write */ | 	/* Read back to ensure completion of the write */ | ||||||
| 	return readl_relaxed(port->base + PORT_RID2SID(idx)); | 	return readl_relaxed(port_rid2sid_addr(port, idx)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int apple_pcie_setup_port(struct apple_pcie *pcie, | static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
|  | @ -484,6 +556,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 	struct platform_device *platform = to_platform_device(pcie->dev); | 	struct platform_device *platform = to_platform_device(pcie->dev); | ||||||
| 	struct apple_pcie_port *port; | 	struct apple_pcie_port *port; | ||||||
| 	struct gpio_desc *reset; | 	struct gpio_desc *reset; | ||||||
|  | 	struct resource *res; | ||||||
|  | 	char name[16]; | ||||||
| 	u32 stat, idx; | 	u32 stat, idx; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
|  | @ -496,6 +570,10 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 	if (!port) | 	if (!port) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
|  | 	port->sid_map = devm_bitmap_zalloc(pcie->dev, pcie->hw->max_rid2sid, GFP_KERNEL); | ||||||
|  | 	if (!port->sid_map) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
| 	ret = of_property_read_u32_index(np, "reg", 0, &idx); | 	ret = of_property_read_u32_index(np, "reg", 0, &idx); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
|  | @ -505,14 +583,28 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 	port->pcie = pcie; | 	port->pcie = pcie; | ||||||
| 	port->np = np; | 	port->np = np; | ||||||
| 
 | 
 | ||||||
| 	port->base = devm_platform_ioremap_resource(platform, port->idx + 2); | 	raw_spin_lock_init(&port->lock); | ||||||
|  | 
 | ||||||
|  | 	snprintf(name, sizeof(name), "port%d", port->idx); | ||||||
|  | 	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name); | ||||||
|  | 	if (!res) | ||||||
|  | 		res = platform_get_resource(platform, IORESOURCE_MEM, port->idx + 2); | ||||||
|  | 
 | ||||||
|  | 	port->base = devm_ioremap_resource(&platform->dev, res); | ||||||
| 	if (IS_ERR(port->base)) | 	if (IS_ERR(port->base)) | ||||||
| 		return PTR_ERR(port->base); | 		return PTR_ERR(port->base); | ||||||
| 
 | 
 | ||||||
|  | 	snprintf(name, sizeof(name), "phy%d", port->idx); | ||||||
|  | 	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name); | ||||||
|  | 	if (res) | ||||||
|  | 		port->phy = devm_ioremap_resource(&platform->dev, res); | ||||||
|  | 	else | ||||||
|  | 		port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx); | ||||||
|  | 
 | ||||||
| 	rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); | 	rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); | ||||||
| 
 | 
 | ||||||
| 	/* Assert PERST# before setting up the clock */ | 	/* Assert PERST# before setting up the clock */ | ||||||
| 	gpiod_set_value(reset, 1); | 	gpiod_set_value_cansleep(reset, 1); | ||||||
| 
 | 
 | ||||||
| 	ret = apple_pcie_setup_refclk(pcie, port); | 	ret = apple_pcie_setup_refclk(pcie, port); | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
|  | @ -522,8 +614,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 	usleep_range(100, 200); | 	usleep_range(100, 200); | ||||||
| 
 | 
 | ||||||
| 	/* Deassert PERST# */ | 	/* Deassert PERST# */ | ||||||
| 	rmw_set(PORT_PERST_OFF, port->base + PORT_PERST); | 	rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst); | ||||||
| 	gpiod_set_value(reset, 0); | 	gpiod_set_value_cansleep(reset, 0); | ||||||
| 
 | 
 | ||||||
| 	/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ | 	/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ | ||||||
| 	msleep(100); | 	msleep(100); | ||||||
|  | @ -535,7 +627,11 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK); | 	if (pcie->hw->port_refclk) | ||||||
|  | 		rmw_clear(PORT_REFCLK_CGDIS, port->base + pcie->hw->port_refclk); | ||||||
|  | 	else | ||||||
|  | 		rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG); | ||||||
|  | 
 | ||||||
| 	rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK); | 	rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK); | ||||||
| 
 | 
 | ||||||
| 	ret = apple_pcie_port_setup_irq(port); | 	ret = apple_pcie_port_setup_irq(port); | ||||||
|  | @ -543,7 +639,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	/* Reset all RID/SID mappings, and check for RAZ/WI registers */ | 	/* Reset all RID/SID mappings, and check for RAZ/WI registers */ | ||||||
| 	for (i = 0; i < MAX_RID2SID; i++) { | 	for (i = 0; i < pcie->hw->max_rid2sid; i++) { | ||||||
| 		if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d) | 		if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d) | ||||||
| 			break; | 			break; | ||||||
| 		apple_pcie_rid2sid_write(port, i, 0); | 		apple_pcie_rid2sid_write(port, i, 0); | ||||||
|  | @ -556,6 +652,9 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, | ||||||
| 	list_add_tail(&port->entry, &pcie->ports); | 	list_add_tail(&port->entry, &pcie->ports); | ||||||
| 	init_completion(&pcie->event); | 	init_completion(&pcie->event); | ||||||
| 
 | 
 | ||||||
|  | 	/* In the success path, we keep a reference to np around */ | ||||||
|  | 	of_node_get(np); | ||||||
|  | 
 | ||||||
| 	ret = apple_pcie_port_register_irqs(port); | 	ret = apple_pcie_port_register_irqs(port); | ||||||
| 	WARN_ON(ret); | 	WARN_ON(ret); | ||||||
| 
 | 
 | ||||||
|  | @ -693,7 +792,7 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci | ||||||
| 	for_each_set_bit(idx, port->sid_map, port->sid_map_sz) { | 	for_each_set_bit(idx, port->sid_map, port->sid_map_sz) { | ||||||
| 		u32 val; | 		u32 val; | ||||||
| 
 | 
 | ||||||
| 		val = readl_relaxed(port->base + PORT_RID2SID(idx)); | 		val = readl_relaxed(port_rid2sid_addr(port, idx)); | ||||||
| 		if ((val & 0xffff) == rid) { | 		if ((val & 0xffff) == rid) { | ||||||
| 			apple_pcie_rid2sid_write(port, idx, 0); | 			apple_pcie_rid2sid_write(port, idx, 0); | ||||||
| 			bitmap_release_region(port->sid_map, idx, 0); | 			bitmap_release_region(port->sid_map, idx, 0); | ||||||
|  | @ -707,34 +806,14 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci | ||||||
| 
 | 
 | ||||||
| static int apple_pcie_init(struct pci_config_window *cfg) | static int apple_pcie_init(struct pci_config_window *cfg) | ||||||
| { | { | ||||||
|  | 	struct apple_pcie *pcie = cfg->priv; | ||||||
| 	struct device *dev = cfg->parent; | 	struct device *dev = cfg->parent; | ||||||
| 	struct platform_device *platform = to_platform_device(dev); |  | ||||||
| 	struct apple_pcie *pcie; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | 	for_each_available_child_of_node_scoped(dev->of_node, of_port) { | ||||||
| 	if (!pcie) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	pcie->dev = dev; |  | ||||||
| 
 |  | ||||||
| 	mutex_init(&pcie->lock); |  | ||||||
| 
 |  | ||||||
| 	pcie->base = devm_platform_ioremap_resource(platform, 1); |  | ||||||
| 	if (IS_ERR(pcie->base)) |  | ||||||
| 		return PTR_ERR(pcie->base); |  | ||||||
| 
 |  | ||||||
| 	cfg->priv = pcie; |  | ||||||
| 	INIT_LIST_HEAD(&pcie->ports); |  | ||||||
| 
 |  | ||||||
| 	ret = apple_msi_init(pcie); |  | ||||||
| 	if (ret) |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	for_each_child_of_node_scoped(dev->of_node, of_port) { |  | ||||||
| 		ret = apple_pcie_setup_port(pcie, of_port); | 		ret = apple_pcie_setup_port(pcie, of_port); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			dev_err(pcie->dev, "Port %pOF setup fail: %d\n", of_port, ret); | 			dev_err(dev, "Port %pOF setup fail: %d\n", of_port, ret); | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -753,14 +832,44 @@ static const struct pci_ecam_ops apple_pcie_cfg_ecam_ops = { | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static int apple_pcie_probe(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct device *dev = &pdev->dev; | ||||||
|  | 	struct apple_pcie *pcie; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | ||||||
|  | 	if (!pcie) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	pcie->dev = dev; | ||||||
|  | 	pcie->hw = of_device_get_match_data(dev); | ||||||
|  | 	if (!pcie->hw) | ||||||
|  | 		return -ENODEV; | ||||||
|  | 	pcie->base = devm_platform_ioremap_resource(pdev, 1); | ||||||
|  | 	if (IS_ERR(pcie->base)) | ||||||
|  | 		return PTR_ERR(pcie->base); | ||||||
|  | 
 | ||||||
|  | 	mutex_init(&pcie->lock); | ||||||
|  | 	INIT_LIST_HEAD(&pcie->ports); | ||||||
|  | 	dev_set_drvdata(dev, pcie); | ||||||
|  | 
 | ||||||
|  | 	ret = apple_msi_init(pcie); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	return pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct of_device_id apple_pcie_of_match[] = { | static const struct of_device_id apple_pcie_of_match[] = { | ||||||
| 	{ .compatible = "apple,pcie", .data = &apple_pcie_cfg_ecam_ops }, | 	{ .compatible = "apple,t6020-pcie",	.data = &t602x_hw }, | ||||||
|  | 	{ .compatible = "apple,pcie",		.data = &t8103_hw }, | ||||||
| 	{ } | 	{ } | ||||||
| }; | }; | ||||||
| MODULE_DEVICE_TABLE(of, apple_pcie_of_match); | MODULE_DEVICE_TABLE(of, apple_pcie_of_match); | ||||||
| 
 | 
 | ||||||
| static struct platform_driver apple_pcie_driver = { | static struct platform_driver apple_pcie_driver = { | ||||||
| 	.probe	= pci_host_common_probe, | 	.probe	= apple_pcie_probe, | ||||||
| 	.driver	= { | 	.driver	= { | ||||||
| 		.name			= "pcie-apple", | 		.name			= "pcie-apple", | ||||||
| 		.of_match_table		= apple_pcie_of_match, | 		.of_match_table		= apple_pcie_of_match, | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds