[PATCH 6.18 081/314] PCI: dw-rockchip: Change get_ltssm() to provide L1 Substates info

Sasha Levin
2026-03-10T11:25:57Z

From: Shawn Lin <shawn.lin@rock-chips.com>

[ Upstream commit f994bb8f1c94726e0124356ccd31c3c23a8a69f4 ]

Rename rockchip_pcie_get_ltssm() to rockchip_pcie_get_ltssm_reg() and add
rockchip_pcie_get_ltssm() to get_ltssm() callback in order to show the
proper L1 Substates. The PCIE_CLIENT_LTSSM_STATUS[5:0] register returns
the same LTSSM layout as enum dw_pcie_ltssm. So the driver just need to
convey L1 PM Substates by returning the proper value defined in
pcie-designware.h.

cat /sys/kernel/debug/dwc_pcie_a40000000.pcie/ltssm_status
L1_2 (0x142)

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/1765503205-22184-2-git-send-email-shawn.lin@rock-chips.com
Stable-dep-of: 180c3cfe3678 ("Revert "PCI: dw-rockchip: Enumerate endpoints based on dll_link_up IRQ"")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 29 ++++++++++++++++---
1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 85999fc316c9f..0a5d1cfb88437 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -68,6 +68,11 @@
#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)

+/* RASDES TBA information */
+#define PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN 0x154
+#define PCIE_CLIENT_CDM_RASDES_TBA_L1_1 BIT(4)
+#define PCIE_CLIENT_CDM_RASDES_TBA_L1_2 BIT(5)
+
/* Hot Reset Control Register */
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
#define PCIE_LTSSM_APP_DLY2_EN BIT(1)
@@ -184,11 +189,26 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)
return 0;
}

-static u32 rockchip_pcie_get_ltssm(struct rockchip_pcie *rockchip)
+static u32 rockchip_pcie_get_ltssm_reg(struct rockchip_pcie *rockchip)
{
return rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS);
}

+static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct dw_pcie *pci)
+{
+ struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+ u32 val = rockchip_pcie_readl_apb(rockchip,
+ PCIE_CLIENT_CDM_RASDES_TBA_INFO_CMN);
+
+ if (val & PCIE_CLIENT_CDM_RASDES_TBA_L1_1)
+ return DW_PCIE_LTSSM_L1_1;
+
+ if (val & PCIE_CLIENT_CDM_RASDES_TBA_L1_2)
+ return DW_PCIE_LTSSM_L1_2;
+
+ return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
+}
+
static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
{
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
@@ -204,7 +224,7 @@ static void rockchip_pcie_disable_ltssm(struct rockchip_pcie *rockchip)
static bool rockchip_pcie_link_up(struct dw_pcie *pci)
{
struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
- u32 val = rockchip_pcie_get_ltssm(rockchip);
+ u32 val = rockchip_pcie_get_ltssm_reg(rockchip);

return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
}
@@ -494,6 +514,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = rockchip_pcie_link_up,
.start_link = rockchip_pcie_start_link,
.stop_link = rockchip_pcie_stop_link,
+ .get_ltssm = rockchip_pcie_get_ltssm,
};

static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
@@ -508,7 +529,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);

dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg);
- dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip));
+ dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm_reg(rockchip));

if (reg & PCIE_RDLH_LINK_UP_CHGED) {
if (rockchip_pcie_link_up(pci)) {
@@ -535,7 +556,7 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);

dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg);
- dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip));
+ dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm_reg(rockchip));

if (reg & PCIE_LINK_REQ_RST_NOT_INT) {
dev_dbg(dev, "hot reset or link-down reset\n");
--
2.51.0