Linux PCI subsystem development
 help / color / mirror / Atom feed
* [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs
@ 2026-06-11 16:59 Hans Zhang
  2026-06-11 16:59 ` [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag Hans Zhang
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Hans Zhang @ 2026-06-11 16:59 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani
  Cc: robh, mpillai, a-garg7, s-vadapalli, linux-pci, linux-kernel,
	Hans Zhang

Hi,

This series adds debugfs support to the Cadence PCIe controller driver,
allowing users to read the current LTSSM state of the link for debugging
purposes.

Patch 1 introduces a new flag 'is_hpa' in the cdns_pcie structure to
distinguish HPA (High Performance Architecture) IP platforms from LGA
(Legacy Architecture) IP platforms, as they have different register
layouts for LTSSM status.

Patch 2 implements the debugfs file "ltssm_status" for HPA IP under a
per-device directory. It reads the LTSSM state from the appropriate
hardware register based on the 'is_hpa' flag and displays both a
descriptive string and the raw value.

Patch 3 adds LTSSM debugfs support for LGA IP, utilizing a new callback
'get_lga_ltssm' in cdns_pcie_ops to read the LTSSM state from the LGA
register. The debugfs interface now supports both IP types seamlessly.

=====================
Test:
root@orangepi6plus:~# ls -l /sys/kernel/debug/cdns_pcie_a0*
/sys/kernel/debug/cdns_pcie_a010000.pcie:
total 0
-r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status

/sys/kernel/debug/cdns_pcie_a0c0000.pcie:
total 0
-r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status

/sys/kernel/debug/cdns_pcie_a0e0000.pcie:
total 0
-r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status
root@orangepi6plus:~# 
root@orangepi6plus:~# 
root@orangepi6plus:~# cat /sys/kernel/debug/cdns_pcie_a0*/ltss*
L0_STATE (0x29)
L0_STATE (0x29)
L0_STATE (0x29)
root@orangepi6plus:~# 
root@orangepi6plus:~# uname -a
Linux orangepi6plus 7.1.0-rc3-00007-ge3963f3f4e31 #62 SMP PREEMPT Tue May 19 20:28:24 CST 2026 aarch64 aarch64 aarch64 GNUx
=====================

---
Changes for v7:
- patch 0002 add MODULE_LICENSE and MODULE_DESCRIPTION (Sashiko and Aksh)
- s/#ifdef CONFIG_PCIE_CADENCE_DEBUGFS/#if IS_ENABLED(CONFIG_PCIE_CADENCE_DEBUGFS)/ (Aksh)
- base on branch: controller/rescan_lock

Changes for v6:
- The LTSSM status of the LGA IP no longer contains the "LTSSM_" character. (Aksh)

Changes for v5:
- Split LGA and HPA LTSSM debugfs support into separate patches as they
  have different register definitions and access methods. (Aksh, Manikandan)
- Add cdns_pcie_hpa_host_disable() to properly clean up debugfs on
  removal (Mani)
- Remove redundant copyright email address (Mani)

Changes for v4:
- Remove the copyright email address of the author of pcie-cadence-debugfs.c (Mani)
- Add cdns_pcie_hpa_host_disable() (Mani)
- Use DEFINE_SHOW_ATTRIBUTE() (Mani & Sashiko)

Changes for v3:
- Export cdns_pcie_debugfs_deinit (Mani)
- pcie-cadence-ep.c pcie-cadence-host.c pci-sky1.c call cdns_pcie_debugfs_deinit

Changes for v2:
- s/DW_PCIE_LTSSM_NAME/CDNS_PCIE_LTSSM_NAME/
- S/January 2026/March 2026/
- EXPORT_SYMBOL_GPL(cdns_pcie_debugfs_init); // Resolve the following error issues.
  >> ERROR: modpost: "cdns_pcie_debugfs_init" [drivers/pci/controller/cadence/pcie-cadence-host-mod.ko] undefined!
  >> ERROR: modpost: "cdns_pcie_debugfs_init" [drivers/pci/controller/cadence/pcie-cadence-ep-mod.ko] undefined!

v6:
https://patchwork.kernel.org/project/linux-pci/cover/20260519123609.1595280-1-18255117159@163.com/
v5:
https://patchwork.kernel.org/project/linux-pci/patch/20260515145747.129635-1-18255117159@163.com/
v4:
https://patchwork.kernel.org/project/linux-pci/patch/20260508034101.1910036-1-18255117159@163.com/
v3:
https://patchwork.kernel.org/project/linux-pci/patch/20260406103237.1203127-1-18255117159@163.com/
v2:
https://patchwork.kernel.org/project/linux-pci/patch/20260321033035.3008585-3-18255117159@163.com/
v1:
https://patchwork.kernel.org/project/linux-pci/cover/20260315155514.127255-1-18255117159@163.com/

Hans Zhang (3):
  PCI: cadence: Add HPA architecture flag
  PCI: cadence: Add HPA IP debugfs for LTSSM status
  PCI: cadence: Add LGA IP debugfs for LTSSM status

 Documentation/ABI/testing/debugfs-cdns-pcie   |   5 +
 drivers/pci/controller/cadence/Kconfig        |   9 +
 drivers/pci/controller/cadence/Makefile       |   1 +
 drivers/pci/controller/cadence/pci-sky1.c     |   5 +
 .../controller/cadence/pcie-cadence-debugfs.c | 266 ++++++++++++++++++
 .../pci/controller/cadence/pcie-cadence-ep.c  |   3 +
 .../cadence/pcie-cadence-host-hpa.c           |  21 +-
 .../controller/cadence/pcie-cadence-host.c    |   9 +-
 drivers/pci/controller/cadence/pcie-cadence.h | 198 +++++++++++++
 9 files changed, 515 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-cdns-pcie
 create mode 100644 drivers/pci/controller/cadence/pcie-cadence-debugfs.c


base-commit: 3a080aa9afb577f7b49d27ace0637222614c9986
-- 
2.34.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag
  2026-06-11 16:59 [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Hans Zhang
@ 2026-06-11 16:59 ` Hans Zhang
  2026-06-11 17:09   ` sashiko-bot
  2026-06-11 16:59 ` [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status Hans Zhang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Hans Zhang @ 2026-06-11 16:59 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani
  Cc: robh, mpillai, a-garg7, s-vadapalli, linux-pci, linux-kernel,
	Hans Zhang

Add a boolean flag 'is_hpa' to the cdns_pcie structure to indicate
that the controller is part of a Heterogeneous Processor Architecture
(HPA) system. This flag will be used by subsequent patches to handle
HPA-specific register layouts and behaviors.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 drivers/pci/controller/cadence/pci-sky1.c     | 1 +
 drivers/pci/controller/cadence/pcie-cadence.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/pci/controller/cadence/pci-sky1.c b/drivers/pci/controller/cadence/pci-sky1.c
index cd55c64e58a9..e1f4a98e2ab6 100644
--- a/drivers/pci/controller/cadence/pci-sky1.c
+++ b/drivers/pci/controller/cadence/pci-sky1.c
@@ -174,6 +174,7 @@ static int sky1_pcie_probe(struct platform_device *pdev)
 	cdns_pcie->reg_base = pcie->reg_base;
 	cdns_pcie->msg_res = pcie->msg_res;
 	cdns_pcie->is_rc = true;
+	cdns_pcie->is_hpa = true;
 
 	reg_off = devm_kzalloc(dev, sizeof(*reg_off), GFP_KERNEL);
 	if (!reg_off) {
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 574e9cf4d003..9a464cbaf073 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -80,6 +80,7 @@ struct cdns_plat_pcie_of_data {
  * @msg_res: Region for send message to map PCI accesses
  * @dev: PCIe controller
  * @is_rc: tell whether the PCIe controller mode is Root Complex or Endpoint.
+ * @is_hpa: indicates if the architecture is HPA
  * @phy_count: number of supported PHY devices
  * @phy: list of pointers to specific PHY control blocks
  * @link: list of pointers to corresponding device link representations
@@ -93,6 +94,7 @@ struct cdns_pcie {
 	struct resource                      *msg_res;
 	struct device		             *dev;
 	bool			             is_rc;
+	bool				     is_hpa;
 	int			             phy_count;
 	struct phy		             **phy;
 	struct device_link	             **link;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status
  2026-06-11 16:59 [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Hans Zhang
  2026-06-11 16:59 ` [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag Hans Zhang
@ 2026-06-11 16:59 ` Hans Zhang
  2026-06-11 17:22   ` sashiko-bot
  2026-06-11 16:59 ` [PATCH v7 3/3] PCI: cadence: Add LGA " Hans Zhang
  2026-06-12  9:30 ` [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Aksh Garg
  3 siblings, 1 reply; 8+ messages in thread
From: Hans Zhang @ 2026-06-11 16:59 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani
  Cc: robh, mpillai, a-garg7, s-vadapalli, linux-pci, linux-kernel,
	Hans Zhang

Add debugfs support for HPA-based Cadence PCIe controllers. A new file
'ltssm_status' is created under debugfs, allowing users to read the
current LTSSM state as a string and raw value.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 Documentation/ABI/testing/debugfs-cdns-pcie   |   5 +
 drivers/pci/controller/cadence/Kconfig        |   9 +
 drivers/pci/controller/cadence/Makefile       |   1 +
 drivers/pci/controller/cadence/pci-sky1.c     |   4 +
 .../controller/cadence/pcie-cadence-debugfs.c | 211 ++++++++++++++++++
 .../cadence/pcie-cadence-host-hpa.c           |  21 +-
 drivers/pci/controller/cadence/pcie-cadence.h | 153 +++++++++++++
 7 files changed, 403 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/debugfs-cdns-pcie
 create mode 100644 drivers/pci/controller/cadence/pcie-cadence-debugfs.c

diff --git a/Documentation/ABI/testing/debugfs-cdns-pcie b/Documentation/ABI/testing/debugfs-cdns-pcie
new file mode 100644
index 000000000000..c1104e28e4ee
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-cdns-pcie
@@ -0,0 +1,5 @@
+What:		/sys/kernel/debug/cdns_pcie_<dev>/ltssm_status
+Date:		March 2026
+Contact:	Hans Zhang <18255117159@163.com>
+Description:	(RO) Read will return the current PCIe LTSSM state in both
+		string and raw value.
\ No newline at end of file
diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
index 9e651d545973..cb010bc97aad 100644
--- a/drivers/pci/controller/cadence/Kconfig
+++ b/drivers/pci/controller/cadence/Kconfig
@@ -6,6 +6,15 @@ menu "Cadence-based PCIe controllers"
 config PCIE_CADENCE
 	tristate
 
+config PCIE_CADENCE_DEBUGFS
+	tristate "Cadence PCIe debugfs entries"
+	depends on DEBUG_FS
+	depends on PCIE_CADENCE_HOST || PCIE_CADENCE_EP
+	help
+	  Say Y here to enable debugfs entries for the PCIe controller. These
+	  entries provide various debug features related to the controller and
+	  the LTSSM status of link can be displayed.
+
 config PCIE_CADENCE_HOST
 	tristate
 	depends on OF
diff --git a/drivers/pci/controller/cadence/Makefile b/drivers/pci/controller/cadence/Makefile
index b8ec1cecfaa8..2cdc4617e0c2 100644
--- a/drivers/pci/controller/cadence/Makefile
+++ b/drivers/pci/controller/cadence/Makefile
@@ -4,6 +4,7 @@ pcie-cadence-host-mod-y := pcie-cadence-host-common.o pcie-cadence-host.o pcie-c
 pcie-cadence-ep-mod-y := pcie-cadence-ep.o
 
 obj-$(CONFIG_PCIE_CADENCE) = pcie-cadence-mod.o
+obj-$(CONFIG_PCIE_CADENCE_DEBUGFS) += pcie-cadence-debugfs.o
 obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host-mod.o
 obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep-mod.o
 obj-$(CONFIG_PCIE_CADENCE_PLAT) += pcie-cadence-plat.o
diff --git a/drivers/pci/controller/cadence/pci-sky1.c b/drivers/pci/controller/cadence/pci-sky1.c
index e1f4a98e2ab6..b8632f1d3156 100644
--- a/drivers/pci/controller/cadence/pci-sky1.c
+++ b/drivers/pci/controller/cadence/pci-sky1.c
@@ -221,6 +221,10 @@ MODULE_DEVICE_TABLE(of, of_sky1_pcie_match);
 static void sky1_pcie_remove(struct platform_device *pdev)
 {
 	struct sky1_pcie *pcie = platform_get_drvdata(pdev);
+	struct cdns_pcie_rc *rc;
+
+	rc = container_of(pcie->cdns_pcie, struct cdns_pcie_rc, pcie);
+	cdns_pcie_hpa_host_disable(rc);
 
 	pci_ecam_free(pcie->cfg);
 }
diff --git a/drivers/pci/controller/cadence/pcie-cadence-debugfs.c b/drivers/pci/controller/cadence/pcie-cadence-debugfs.c
new file mode 100644
index 000000000000..61960840ba67
--- /dev/null
+++ b/drivers/pci/controller/cadence/pcie-cadence-debugfs.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cadence PCIe controller debugfs driver
+ *
+ * Copyright (C) 2026 Hans Zhang <18255117159@163.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "pcie-cadence.h"
+
+#define CDNS_DEBUGFS_BUF_MAX		128
+
+static const char *cdns_pcie_hpa_ltssm_status_string(enum cdns_pcie_hpa_ltssm ltssm)
+{
+	const char *str;
+
+	switch (ltssm) {
+#define CDNS_PCIE_HPA_LTSSM_NAME(n) case n: str = #n; break
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_QUIET);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_QUIET_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RCVR_DETECTED_ST);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RCVR_DETECTED_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_ACC_RC);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_RC);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_RC_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_RC);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LW_ACC_EP);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_EP);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_EP_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_EP);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_EP_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_IDLE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_CONFIG_IDLE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0_STATE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_LOCK);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_LOCK_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_CFG);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_CFG_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_IDLE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_IDLE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_6);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_7);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_HOT_RESET);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_HOT_RESET_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_HOT_RESET_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_HOT_RESET_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L0S_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_WAIT_FOR_LINK_TX);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_FTS_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_FTS_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_FTS_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_ST);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_6);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_7);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_8);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ENTRY_FROM_RECOVERY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_EXIT_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_EXIT);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ACTIVE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_IDLE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L1_EXIT);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_L2_IDLE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_3);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_4);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_5);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_FROM_RECOVERY);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ACTIVE);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE0);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE2_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE2_2);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE3_1);
+	CDNS_PCIE_HPA_LTSSM_NAME(CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE3_2);
+	default:
+		str = "CDNS_PCIE_HPA_LTSSM_UNKNOWN";
+		break;
+	}
+
+	return str + strlen("CDNS_PCIE_HPA_LTSSM_");
+}
+
+static int ltssm_status_show(struct seq_file *s, void *v)
+{
+	struct cdns_pcie *pci = s->private;
+	enum cdns_pcie_hpa_ltssm hpa_ltssm;
+	const char *str_ltssm;
+	u32 val;
+
+	if (pci->is_hpa) {
+		val = cdns_pcie_hpa_readl(pci, REG_BANK_IP_REG,
+					  CDNS_PCIE_HPA_PHY_DBG_STS_REG0);
+		hpa_ltssm = FIELD_GET(CDNS_PCIE_HPA_LTSSM_STATUS_MASK, val);
+		str_ltssm = cdns_pcie_hpa_ltssm_status_string(hpa_ltssm);
+	} else {
+		/* TODO: LGA IP*/
+		return 0;
+	}
+
+	seq_printf(s, "%s (0x%02x)\n", str_ltssm, hpa_ltssm);
+
+	return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(ltssm_status);
+
+static void cdns_pcie_ltssm_debugfs_init(struct cdns_pcie *pci, struct dentry *dir)
+{
+	debugfs_create_file("ltssm_status", 0444, dir, pci,
+			    &ltssm_status_fops);
+}
+
+void cdns_pcie_debugfs_deinit(struct cdns_pcie *pci)
+{
+	if (!pci->debug_dir)
+		return;
+
+	debugfs_remove_recursive(pci->debug_dir);
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_debugfs_deinit);
+
+void cdns_pcie_debugfs_init(struct cdns_pcie *pci)
+{
+	char dirname[CDNS_DEBUGFS_BUF_MAX];
+	struct device *dev = pci->dev;
+
+	/* Create main directory for each platform driver. */
+	snprintf(dirname, CDNS_DEBUGFS_BUF_MAX, "cdns_pcie_%s", dev_name(dev));
+	pci->debug_dir = debugfs_create_dir(dirname, NULL);
+
+	cdns_pcie_ltssm_debugfs_init(pci, pci->debug_dir);
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_debugfs_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence PCIe debugfs driver");
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
index 0f540bed58e8..89f1d75c2c38 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
@@ -309,6 +309,19 @@ int cdns_pcie_hpa_host_link_setup(struct cdns_pcie_rc *rc)
 }
 EXPORT_SYMBOL_GPL(cdns_pcie_hpa_host_link_setup);
 
+void cdns_pcie_hpa_host_disable(struct cdns_pcie_rc *rc)
+{
+	struct pci_host_bridge *bridge;
+
+	cdns_pcie_debugfs_deinit(&rc->pcie);
+	bridge = pci_host_bridge_from_priv(rc);
+	pci_lock_rescan_remove();
+	pci_stop_root_bus(bridge->bus);
+	pci_remove_root_bus(bridge->bus);
+	pci_unlock_rescan_remove();
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_hpa_host_disable);
+
 int cdns_pcie_hpa_host_setup(struct cdns_pcie_rc *rc)
 {
 	struct device *dev = rc->pcie.dev;
@@ -360,7 +373,13 @@ int cdns_pcie_hpa_host_setup(struct cdns_pcie_rc *rc)
 	if (!bridge->ops)
 		bridge->ops = &cdns_pcie_hpa_host_ops;
 
-	return pci_host_probe(bridge);
+	ret = pci_host_probe(bridge);
+	if (ret)
+		return ret;
+
+	cdns_pcie_debugfs_init(pcie);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(cdns_pcie_hpa_host_setup);
 
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 9a464cbaf073..8de292405765 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -14,6 +14,8 @@
 #include "pcie-cadence-lga-regs.h"
 #include "pcie-cadence-hpa-regs.h"
 
+#define CDNS_PCIE_HPA_LTSSM_STATUS_MASK	GENMASK(27, 20)
+
 enum cdns_pcie_rp_bar {
 	RP_BAR_UNDEFINED = -1,
 	RP_BAR0,
@@ -42,6 +44,138 @@ enum cdns_pcie_reg_bank {
 	REG_BANKS_MAX,
 };
 
+enum cdns_pcie_hpa_ltssm {
+	CDNS_PCIE_HPA_LTSSM_DETECT_QUIET		= 0,
+	CDNS_PCIE_HPA_LTSSM_DETECT_QUIET_ENTRY		= 1,
+	CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE		= 2,
+	CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_1		= 3,
+	CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_2		= 4,
+	CDNS_PCIE_HPA_LTSSM_DETECT_ACTIVE_3		= 5,
+	CDNS_PCIE_HPA_LTSSM_RCVR_DETECTED_ST		= 6,
+	CDNS_PCIE_HPA_LTSSM_RCVR_DETECTED_1		= 7,
+	CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE		= 8,
+	CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_1		= 9,
+	CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_2		= 10,
+	CDNS_PCIE_HPA_LTSSM_POLLING_ACTIVE_3		= 11,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE		= 12,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_1	= 13,
+	CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG		= 14,
+	CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG_1		= 15,
+	CDNS_PCIE_HPA_LTSSM_POLLING_CONFIG_2		= 16,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC		= 17,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC_1	= 18,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_RC_2	= 19,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_ACC_RC		= 20,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_RC	= 21,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_RC_1	= 22,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_RC	= 23,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP		= 24,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP_1	= 25,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_START_EP_2	= 26,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LW_ACC_EP		= 27,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_EP	= 28,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_WAIT_EP_1	= 29,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_EP	= 30,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_LANENUM_ACC_EP_1	= 31,
+	CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_1		= 32,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE		= 33,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE_1		= 34,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_COMPLETE_2		= 35,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_IDLE			= 36,
+	CDNS_PCIE_HPA_LTSSM_CONFIG_IDLE_1		= 37,
+	CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_2		= 38,
+	CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_3		= 39,
+	CDNS_PCIE_HPA_LTSSM_DUMMY_STATE_4		= 40,
+	CDNS_PCIE_HPA_LTSSM_L0_STATE			= 41,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_LOCK		= 42,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_LOCK_1	= 43,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_CFG		= 44,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_RCVR_CFG_1		= 45,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_IDLE		= 46,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_IDLE_1		= 47,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK		= 48,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_1		= 49,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_2		= 50,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_3		= 51,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_4		= 52,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_5		= 53,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_6		= 54,
+	CDNS_PCIE_HPA_LTSSM_DISABLE_LINK_7		= 55,
+	CDNS_PCIE_HPA_LTSSM_HOT_RESET			= 56,
+	CDNS_PCIE_HPA_LTSSM_HOT_RESET_1			= 57,
+	CDNS_PCIE_HPA_LTSSM_HOT_RESET_2			= 58,
+	CDNS_PCIE_HPA_LTSSM_HOT_RESET_3			= 59,
+	CDNS_PCIE_HPA_LTSSM_L0S_ENTRY			= 60,
+	CDNS_PCIE_HPA_LTSSM_L0S_1			= 61,
+	CDNS_PCIE_HPA_LTSSM_L0S_2			= 62,
+	CDNS_PCIE_HPA_LTSSM_L0S_3			= 63,
+	CDNS_PCIE_HPA_LTSSM_L0S_4			= 64,
+	CDNS_PCIE_HPA_LTSSM_L0S_5			= 65,
+	CDNS_PCIE_HPA_LTSSM_WAIT_FOR_LINK_TX		= 66,
+	CDNS_PCIE_HPA_LTSSM_TX_FTS_ENTRY		= 67,
+	CDNS_PCIE_HPA_LTSSM_TX_FTS_1			= 68,
+	CDNS_PCIE_HPA_LTSSM_TX_FTS_2			= 69,
+	CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_ST		= 70,
+	CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_1		= 71,
+	CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_2		= 72,
+	CDNS_PCIE_HPA_LTSSM_TX_ELEC_IDLE_3		= 73,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED		= 74,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_1		= 75,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_2		= 76,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_SPEED_3		= 77,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23	= 78,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_1	= 79,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_2	= 80,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_3	= 81,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_4	= 82,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_5	= 83,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_6	= 84,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_7	= 85,
+	CDNS_PCIE_HPA_LTSSM_POLLING_COMPLIANCE_GEN23_8	= 86,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ENTRY	= 87,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ENTRY_FROM_RECOVERY = 88,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_EXIT_1	= 89,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_EXIT		= 90,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_1	= 91,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_2	= 92,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_3	= 93,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_4	= 94,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_GEN2_5	= 95,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_SLAVE_ACTIVE	= 96,
+	CDNS_PCIE_HPA_LTSSM_L1_ENTRY			= 97,
+	CDNS_PCIE_HPA_LTSSM_L1_1			= 98,
+	CDNS_PCIE_HPA_LTSSM_L1_2			= 99,
+	CDNS_PCIE_HPA_LTSSM_L1_3			= 100,
+	CDNS_PCIE_HPA_LTSSM_L1_4			= 101,
+	CDNS_PCIE_HPA_LTSSM_L1_IDLE			= 102,
+	CDNS_PCIE_HPA_LTSSM_L1_EXIT			= 103,
+	CDNS_PCIE_HPA_LTSSM_L2_ENTRY			= 104,
+	CDNS_PCIE_HPA_LTSSM_L2_1			= 105,
+	CDNS_PCIE_HPA_LTSSM_L2_2			= 106,
+	CDNS_PCIE_HPA_LTSSM_L2_3			= 107,
+	CDNS_PCIE_HPA_LTSSM_L2_4			= 108,
+	CDNS_PCIE_HPA_LTSSM_L2_5			= 109,
+	CDNS_PCIE_HPA_LTSSM_L2_IDLE			= 110,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY	= 111,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_1	= 112,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_2	= 113,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_3	= 114,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_4	= 115,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_5	= 116,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ENTRY_FROM_RECOVERY = 117,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_ACTIVE	= 118,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT	= 119,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT_1	= 120,
+	CDNS_PCIE_HPA_LTSSM_LOOPBACK_MASTER_EXIT_2	= 121,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 122,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 123,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE2_1 = 124,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE2_2 = 125,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE3_1 = 126,
+	CDNS_PCIE_HPA_LTSSM_RECOVERY_EQUALIZATION_PHASE3_2 = 127,
+	CDNS_PCIE_HPA_LTSSM_UNKNOWN			= 0xFFFFFFFF,
+};
+
 struct cdns_pcie_ops {
 	int     (*start_link)(struct cdns_pcie *pcie);
 	void    (*stop_link)(struct cdns_pcie *pcie);
@@ -87,6 +221,7 @@ struct cdns_plat_pcie_of_data {
  * @ops: Platform-specific ops to control various inputs from Cadence PCIe
  *       wrapper
  * @cdns_pcie_reg_offsets: Register bank offsets for different SoC
+ * @debug_dir: debugfs node
  */
 struct cdns_pcie {
 	void __iomem		             *reg_base;
@@ -100,6 +235,7 @@ struct cdns_pcie {
 	struct device_link	             **link;
 	const  struct cdns_pcie_ops          *ops;
 	const  struct cdns_plat_pcie_of_data *cdns_pcie_reg_offsets;
+	struct dentry			     *debug_dir;
 };
 
 /**
@@ -447,6 +583,7 @@ void cdns_pcie_host_disable(struct cdns_pcie_rc *rc);
 void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 			       int where);
 int cdns_pcie_hpa_host_setup(struct cdns_pcie_rc *rc);
+void cdns_pcie_hpa_host_disable(struct cdns_pcie_rc *rc);
 #else
 static inline int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
 {
@@ -472,6 +609,10 @@ static inline void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
 {
 }
 
+static inline void cdns_pcie_hpa_host_disable(struct cdns_pcie_rc *rc)
+{
+}
+
 static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 					     int where)
 {
@@ -535,4 +676,16 @@ bool cdns_pcie_hpa_link_up(struct cdns_pcie *pcie);
 
 extern const struct dev_pm_ops cdns_pcie_pm_ops;
 
+#if IS_ENABLED(CONFIG_PCIE_CADENCE_DEBUGFS)
+void cdns_pcie_debugfs_deinit(struct cdns_pcie *pci);
+void cdns_pcie_debugfs_init(struct cdns_pcie *pci);
+#else
+static inline void cdns_pcie_debugfs_deinit(struct cdns_pcie *pci)
+{
+}
+static inline void cdns_pcie_debugfs_init(struct cdns_pcie *pci)
+{
+}
+#endif
+
 #endif /* _PCIE_CADENCE_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v7 3/3] PCI: cadence: Add LGA IP debugfs for LTSSM status
  2026-06-11 16:59 [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Hans Zhang
  2026-06-11 16:59 ` [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag Hans Zhang
  2026-06-11 16:59 ` [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status Hans Zhang
@ 2026-06-11 16:59 ` Hans Zhang
  2026-06-11 17:35   ` sashiko-bot
  2026-06-12  9:30 ` [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Aksh Garg
  3 siblings, 1 reply; 8+ messages in thread
From: Hans Zhang @ 2026-06-11 16:59 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kwilczynski, mani
  Cc: robh, mpillai, a-garg7, s-vadapalli, linux-pci, linux-kernel,
	Hans Zhang

Extend debugfs support to LGA-based Cadence PCIe controllers. The
'ltssm_status' file now works for both HPA and LGA IP by selecting the
appropriate register access based on the 'is_hpa' flag.

Signed-off-by: Hans Zhang <18255117159@163.com>
---
 .../controller/cadence/pcie-cadence-debugfs.c | 61 ++++++++++++++++++-
 .../pci/controller/cadence/pcie-cadence-ep.c  |  3 +
 .../controller/cadence/pcie-cadence-host.c    |  9 ++-
 drivers/pci/controller/cadence/pcie-cadence.h | 43 +++++++++++++
 4 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-debugfs.c b/drivers/pci/controller/cadence/pcie-cadence-debugfs.c
index 61960840ba67..6e34138e165b 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-debugfs.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-debugfs.c
@@ -13,6 +13,58 @@
 
 #define CDNS_DEBUGFS_BUF_MAX		128
 
+static const char *cdns_pcie_lga_ltssm_status_string(enum cdns_pcie_lga_ltssm ltssm)
+{
+	const char *str;
+
+	switch (ltssm) {
+#define CDNS_PCIE_LGA_LTSSM_NAME(n) case n: str = #n; break
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_DETECT_QUIET);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_DETECT_ACTIVE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_POLLING_ACTIVE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_POLLING_COMPLIANCE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_POLLING_CONFIGURATION);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LINKWIDTH_START);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LINKWIDTH_ACCEPT);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LANENUM_ACCEPT);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LANENUM_WAIT);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_COMPLETE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_CONFIGURATION_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_RCVRLOCK);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_SPEED);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_RCVRCFG);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_L0);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RX_L0S_ENTRY);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RX_L0S_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RX_L0S_FTS);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_TX_L0S_ENTRY);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_TX_L0S_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_TX_L0S_FTS);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_L1_ENTRY);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_L1_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_L2_IDLE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_L2_TRANSMITWAKE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_DISABLED);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_ENTRY_MASTER);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_ACTIVE_MASTER);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_EXIT_MASTER);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_ENTRY_SLAVE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_ACTIVE_SLAVE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_LOOPBACK_EXIT_SLAVE);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_HOT_RESET);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_0);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_1);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_2);
+	CDNS_PCIE_LGA_LTSSM_NAME(CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_3);
+	default:
+		str = "CDNS_PCIE_LGA_LTSSM_UNKNOWN";
+		break;
+	}
+
+	return str + strlen("CDNS_PCIE_LGA_LTSSM_");
+}
+
 static const char *cdns_pcie_hpa_ltssm_status_string(enum cdns_pcie_hpa_ltssm ltssm)
 {
 	const char *str;
@@ -158,6 +210,7 @@ static const char *cdns_pcie_hpa_ltssm_status_string(enum cdns_pcie_hpa_ltssm lt
 static int ltssm_status_show(struct seq_file *s, void *v)
 {
 	struct cdns_pcie *pci = s->private;
+	enum cdns_pcie_lga_ltssm lga_ltssm;
 	enum cdns_pcie_hpa_ltssm hpa_ltssm;
 	const char *str_ltssm;
 	u32 val;
@@ -168,11 +221,13 @@ static int ltssm_status_show(struct seq_file *s, void *v)
 		hpa_ltssm = FIELD_GET(CDNS_PCIE_HPA_LTSSM_STATUS_MASK, val);
 		str_ltssm = cdns_pcie_hpa_ltssm_status_string(hpa_ltssm);
 	} else {
-		/* TODO: LGA IP*/
-		return 0;
+		val = cdns_pcie_readl(pci, CDNS_PCIE_LM_BASE);
+		lga_ltssm = FIELD_GET(CDNS_PCIE_LGA_LTSSM_STATUS_MASK, val);
+		str_ltssm = cdns_pcie_lga_ltssm_status_string(lga_ltssm);
 	}
 
-	seq_printf(s, "%s (0x%02x)\n", str_ltssm, hpa_ltssm);
+	seq_printf(s, "%s (0x%02x)\n", str_ltssm,
+		   pci->is_hpa ? hpa_ltssm : lga_ltssm);
 
 	return 0;
 }
diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index c0e1194a936b..370b19f4d38f 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -655,6 +655,7 @@ void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
 	struct device *dev = ep->pcie.dev;
 	struct pci_epc *epc = to_pci_epc(dev);
 
+	cdns_pcie_debugfs_deinit(&ep->pcie);
 	pci_epc_deinit_notify(epc);
 	pci_epc_mem_free_addr(epc, ep->irq_phys_addr, ep->irq_cpu_addr,
 			      SZ_128K);
@@ -761,6 +762,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 
 	pci_epc_init_notify(epc);
 
+	cdns_pcie_debugfs_init(pcie);
+
 	return 0;
 
  free_epc_mem:
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 87fd8afa301b..2ab8d8ac0595 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -364,6 +364,7 @@ void cdns_pcie_host_disable(struct cdns_pcie_rc *rc)
 {
 	struct pci_host_bridge *bridge;
 
+	cdns_pcie_debugfs_deinit(&rc->pcie);
 	bridge = pci_host_bridge_from_priv(rc);
 	pci_lock_rescan_remove();
 	pci_stop_root_bus(bridge->bus);
@@ -425,7 +426,13 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
 	if (!bridge->ops)
 		bridge->ops = &cdns_pcie_host_ops;
 
-	return pci_host_probe(bridge);
+	ret = pci_host_probe(bridge);
+	if (ret)
+		return ret;
+
+	cdns_pcie_debugfs_init(pcie);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(cdns_pcie_host_setup);
 
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 8de292405765..195c42140f29 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -14,6 +14,7 @@
 #include "pcie-cadence-lga-regs.h"
 #include "pcie-cadence-hpa-regs.h"
 
+#define CDNS_PCIE_LGA_LTSSM_STATUS_MASK	GENMASK(29, 24)
 #define CDNS_PCIE_HPA_LTSSM_STATUS_MASK	GENMASK(27, 20)
 
 enum cdns_pcie_rp_bar {
@@ -44,6 +45,48 @@ enum cdns_pcie_reg_bank {
 	REG_BANKS_MAX,
 };
 
+enum cdns_pcie_lga_ltssm {
+	CDNS_PCIE_LGA_LTSSM_DETECT_QUIET			= 0x00,
+	CDNS_PCIE_LGA_LTSSM_DETECT_ACTIVE			= 0x01,
+	CDNS_PCIE_LGA_LTSSM_POLLING_ACTIVE			= 0x02,
+	CDNS_PCIE_LGA_LTSSM_POLLING_COMPLIANCE			= 0x03,
+	CDNS_PCIE_LGA_LTSSM_POLLING_CONFIGURATION		= 0x04,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LINKWIDTH_START	= 0x05,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LINKWIDTH_ACCEPT	= 0x06,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LANENUM_ACCEPT	= 0x07,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_LANENUM_WAIT		= 0x08,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_COMPLETE		= 0x09,
+	CDNS_PCIE_LGA_LTSSM_CONFIGURATION_IDLE			= 0x0A,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_RCVRLOCK			= 0x0B,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_SPEED			= 0x0C,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_RCVRCFG			= 0x0D,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_IDLE			= 0x0E,
+	CDNS_PCIE_LGA_LTSSM_L0					= 0x10,
+	CDNS_PCIE_LGA_LTSSM_RX_L0S_ENTRY			= 0x11,
+	CDNS_PCIE_LGA_LTSSM_RX_L0S_IDLE				= 0x12,
+	CDNS_PCIE_LGA_LTSSM_RX_L0S_FTS				= 0x13,
+	CDNS_PCIE_LGA_LTSSM_TX_L0S_ENTRY			= 0x14,
+	CDNS_PCIE_LGA_LTSSM_TX_L0S_IDLE				= 0x15,
+	CDNS_PCIE_LGA_LTSSM_TX_L0S_FTS				= 0x16,
+	CDNS_PCIE_LGA_LTSSM_L1_ENTRY				= 0x17,
+	CDNS_PCIE_LGA_LTSSM_L1_IDLE				= 0x18,
+	CDNS_PCIE_LGA_LTSSM_L2_IDLE				= 0x19,
+	CDNS_PCIE_LGA_LTSSM_L2_TRANSMITWAKE			= 0x1A,
+	CDNS_PCIE_LGA_LTSSM_DISABLED				= 0x20,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_ENTRY_MASTER		= 0x21,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_ACTIVE_MASTER		= 0x22,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_EXIT_MASTER		= 0x23,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_ENTRY_SLAVE		= 0x24,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_ACTIVE_SLAVE		= 0x25,
+	CDNS_PCIE_LGA_LTSSM_LOOPBACK_EXIT_SLAVE			= 0x26,
+	CDNS_PCIE_LGA_LTSSM_HOT_RESET				= 0x27,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_0	= 0x28,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_1	= 0x29,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_2	= 0x2A,
+	CDNS_PCIE_LGA_LTSSM_RECOVERY_EQUALIZATION_PHASE_3	= 0x2B,
+	CDNS_PCIE_LGA_LTSSM_UNKNOWN				= 0xFFFFFFFF,
+};
+
 enum cdns_pcie_hpa_ltssm {
 	CDNS_PCIE_HPA_LTSSM_DETECT_QUIET		= 0,
 	CDNS_PCIE_HPA_LTSSM_DETECT_QUIET_ENTRY		= 1,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag
  2026-06-11 16:59 ` [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag Hans Zhang
@ 2026-06-11 17:09   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-06-11 17:09 UTC (permalink / raw)
  To: Hans Zhang; +Cc: linux-pci

> Add a boolean flag 'is_hpa' to the cdns_pcie structure to indicate
> that the controller is part of a Heterogeneous Processor Architecture
> (HPA) system. This flag will be used by subsequent patches to handle
> HPA-specific register layouts and behaviors.
> 
> Signed-off-by: Hans Zhang <18255117159@163.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260611165933.20071-1-18255117159@163.com?part=1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status
  2026-06-11 16:59 ` [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status Hans Zhang
@ 2026-06-11 17:22   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-06-11 17:22 UTC (permalink / raw)
  To: Hans Zhang; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Building PCIE_CADENCE_HOST as built-in and PCIE_CADENCE_DEBUGFS as a module results in a linkage error.
--

commit 20cc8aa0f1ba6b094082684b8473490c278a0462
Author: Hans Zhang <18255117159@163.com>

PCI: cadence: Add HPA IP debugfs for LTSSM status

This commit adds debugfs support for HPA-based Cadence PCIe controllers.
It creates a new ltssm_status file under debugfs to allow users to read
the current LTSSM state as a string and raw value.

> diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
> index 9e651d5459735..cb010bc97aad3 100644
> --- a/drivers/pci/controller/cadence/Kconfig
> +++ b/drivers/pci/controller/cadence/Kconfig
> @@ -6,6 +6,15 @@ menu "Cadence-based PCIe controllers"
>  config PCIE_CADENCE
>  	tristate
>  
> +config PCIE_CADENCE_DEBUGFS
> +	tristate "Cadence PCIe debugfs entries"
> +	depends on DEBUG_FS
> +	depends on PCIE_CADENCE_HOST || PCIE_CADENCE_EP

[ ... ]

> diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
> index 9a464cbaf073d..8de2924057659 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence.h
> +++ b/drivers/pci/controller/cadence/pcie-cadence.h

[ ... ]

> @@ -535,4 +676,16 @@ bool cdns_pcie_hpa_link_up(struct cdns_pcie *pcie);
>  
>  extern const struct dev_pm_ops cdns_pcie_pm_ops;
>  
> +#if IS_ENABLED(CONFIG_PCIE_CADENCE_DEBUGFS)
> +void cdns_pcie_debugfs_deinit(struct cdns_pcie *pci);
> +void cdns_pcie_debugfs_init(struct cdns_pcie *pci);
> +#else
> +static inline void cdns_pcie_debugfs_deinit(struct cdns_pcie *pci)
> +{
> +}
> +static inline void cdns_pcie_debugfs_init(struct cdns_pcie *pci)
> +{
> +}
> +#endif

[Severity: Low]
Does this cause a linkage error if CONFIG_PCIE_CADENCE_HOST is built-in (=y)
and CONFIG_PCIE_CADENCE_DEBUGFS is built as a module (=m)?

When configured this way, IS_ENABLED(CONFIG_PCIE_CADENCE_DEBUGFS) evaluates
to 1, so the preprocessor does not provide the empty inline stubs. Then,
when the built-in host code calls cdns_pcie_debugfs_init(), it results in
an undefined reference at vmlinux link time because the debugfs code is in
a separate module.

Would using IS_REACHABLE() instead of IS_ENABLED(), or restricting the
tristate dependencies in Kconfig, prevent this build failure?

> diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
> index 0f540bed58e88..89f1d75c2c38d 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c

[ ... ]

> @@ -360,7 +373,13 @@ int cdns_pcie_hpa_host_setup(struct cdns_pcie_rc *rc)
>  	if (!bridge->ops)
>  		bridge->ops = &cdns_pcie_hpa_host_ops;
>  
> -	return pci_host_probe(bridge);
> +	ret = pci_host_probe(bridge);
> +	if (ret)
> +		return ret;
> +
> +	cdns_pcie_debugfs_init(pcie);
> +
> +	return 0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260611165933.20071-1-18255117159@163.com?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v7 3/3] PCI: cadence: Add LGA IP debugfs for LTSSM status
  2026-06-11 16:59 ` [PATCH v7 3/3] PCI: cadence: Add LGA " Hans Zhang
@ 2026-06-11 17:35   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-06-11 17:35 UTC (permalink / raw)
  To: Hans Zhang; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Invalid pointer derivation via `to_pci_epc()` in `cdns_pcie_ep_disable()` leading to a wild pointer dereference.
- [High] The `pcie-cadence-plat.c` driver incorrectly returns 0 on probe failure and lacks a `.remove` callback, leading to silent probe failures and severe use-after-free bugs on unbind.
--

commit b49dbfe29c305b407944a72dcdee68320ac08c7c
Author: Hans Zhang <18255117159@163.com>

PCI: cadence: Add LGA IP debugfs for LTSSM status

This commit extends debugfs support to LGA-based Cadence PCIe controllers.
The 'ltssm_status' file now supports both HPA and LGA IP by selecting the
appropriate register access based on the 'is_hpa' flag.

> diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> index c0e1194a936b3..370b19f4d38fb 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> @@ -655,6 +655,7 @@ void cdns_pcie_ep_disable(struct cdns_pcie_ep *ep)
>  	struct device *dev = ep->pcie.dev;
>  	struct pci_epc *epc = to_pci_epc(dev);

[Severity: High]
This isn't a bug introduced by this patch, but can this lead to a wild pointer
dereference?

In cdns_pcie_ep_setup(), the epc object is allocated separately using
devm_pci_epc_create(), which embeds its own struct device (epc->dev).

Here in cdns_pcie_ep_disable(), the code attempts to recover the epc pointer
by passing the parent platform device (ep->pcie.dev) to to_pci_epc().

Because to_pci_epc() is a container_of macro, subtracting the offset of the
dev member from the platform device pointer will yield an invalid pointer.

Will dereferencing this pointer in downstream functions like
pci_epc_deinit_notify() cause memory corruption or a kernel panic during
driver unbind?

>  
> +	cdns_pcie_debugfs_deinit(&ep->pcie);
>  	pci_epc_deinit_notify(epc);
>  	pci_epc_mem_free_addr(epc, ep->irq_phys_addr, ep->irq_cpu_addr,
>  			      SZ_128K);

[ ... ]

I also noticed a pre-existing issue in drivers/pci/controller/cadence/pcie-cadence-plat.c:

drivers/pci/controller/cadence/pcie-cadence-plat.c:cdns_plat_pcie_probe() {
    ...
 err_init:
 err_get_sync:
	pm_runtime_put_sync(dev);
	pm_runtime_disable(dev);
	cdns_pcie_disable_phy(cdns_plat_pcie->pcie);
	phy_count = cdns_plat_pcie->pcie->phy_count;
	while (phy_count--)
		device_link_del(cdns_plat_pcie->pcie->link[phy_count]);

	return 0;
}

[Severity: High]
This isn't a bug introduced by this patch, but does returning 0 here silently
mask probe failures from the driver core?

Also, the platform driver lacks a .remove callback:

static struct platform_driver cdns_plat_pcie_driver = {
	.driver = {
		.name = "cdns-pcie",
		.of_match_table = cdns_plat_pcie_of_match,
		.pm	= &cdns_pcie_pm_ops,
	},
	.probe = cdns_plat_pcie_probe,
	.shutdown = cdns_plat_pcie_shutdown,
};

Does the lack of a .remove callback mean no driver-specific teardown runs
on unbind?

Without it, devres will free the controller memory while leaving the active
PCI root bus and debugfs nodes with dangling pointers.  Could this result in
use-after-free bugs when those pointers are accessed?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260611165933.20071-1-18255117159@163.com?part=3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs
  2026-06-11 16:59 [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Hans Zhang
                   ` (2 preceding siblings ...)
  2026-06-11 16:59 ` [PATCH v7 3/3] PCI: cadence: Add LGA " Hans Zhang
@ 2026-06-12  9:30 ` Aksh Garg
  3 siblings, 0 replies; 8+ messages in thread
From: Aksh Garg @ 2026-06-12  9:30 UTC (permalink / raw)
  To: Hans Zhang, bhelgaas, lpieralisi, kwilczynski, mani
  Cc: robh, mpillai, s-vadapalli, linux-pci, linux-kernel



On 11/06/26 22:29, Hans Zhang wrote:
> Hi,
> 
> This series adds debugfs support to the Cadence PCIe controller driver,
> allowing users to read the current LTSSM state of the link for debugging
> purposes.
> 
> Patch 1 introduces a new flag 'is_hpa' in the cdns_pcie structure to
> distinguish HPA (High Performance Architecture) IP platforms from LGA
> (Legacy Architecture) IP platforms, as they have different register
> layouts for LTSSM status.
> 
> Patch 2 implements the debugfs file "ltssm_status" for HPA IP under a
> per-device directory. It reads the LTSSM state from the appropriate
> hardware register based on the 'is_hpa' flag and displays both a
> descriptive string and the raw value.
> 
> Patch 3 adds LTSSM debugfs support for LGA IP, utilizing a new callback
> 'get_lga_ltssm' in cdns_pcie_ops to read the LTSSM state from the LGA
> register. The debugfs interface now supports both IP types seamlessly.
> 
> =====================
> Test:
> root@orangepi6plus:~# ls -l /sys/kernel/debug/cdns_pcie_a0*
> /sys/kernel/debug/cdns_pcie_a010000.pcie:
> total 0
> -r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status
> 
> /sys/kernel/debug/cdns_pcie_a0c0000.pcie:
> total 0
> -r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status
> 
> /sys/kernel/debug/cdns_pcie_a0e0000.pcie:
> total 0
> -r--r--r-- 1 root root 0 Jan  1  1970 ltssm_status
> root@orangepi6plus:~#
> root@orangepi6plus:~#
> root@orangepi6plus:~# cat /sys/kernel/debug/cdns_pcie_a0*/ltss*
> L0_STATE (0x29)
> L0_STATE (0x29)
> L0_STATE (0x29)
> root@orangepi6plus:~#
> root@orangepi6plus:~# uname -a
> Linux orangepi6plus 7.1.0-rc3-00007-ge3963f3f4e31 #62 SMP PREEMPT Tue May 19 20:28:24 CST 2026 aarch64 aarch64 aarch64 GNUx
> =====================
> 
> ---

Hi,

I have tested the series for LGA IP:

Tested-by: Aksh Garg <a-garg7@ti.com>

Regards,
Aksh Garg



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-06-12  9:30 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-11 16:59 [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Hans Zhang
2026-06-11 16:59 ` [PATCH v7 1/3] PCI: cadence: Add HPA architecture flag Hans Zhang
2026-06-11 17:09   ` sashiko-bot
2026-06-11 16:59 ` [PATCH v7 2/3] PCI: cadence: Add HPA IP debugfs for LTSSM status Hans Zhang
2026-06-11 17:22   ` sashiko-bot
2026-06-11 16:59 ` [PATCH v7 3/3] PCI: cadence: Add LGA " Hans Zhang
2026-06-11 17:35   ` sashiko-bot
2026-06-12  9:30 ` [PATCH v7 0/3] PCI: cadence: Add LTSSM debugfs Aksh Garg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox