* [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-11 22:16 [PATCH 0/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it Bjorn Helgaas
@ 2025-11-11 22:16 ` Bjorn Helgaas
2025-11-11 22:48 ` Frank Li
` (2 more replies)
2025-11-11 22:16 ` [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code Bjorn Helgaas
` (2 subsequent siblings)
3 siblings, 3 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-11 22:16 UTC (permalink / raw)
To: Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
From: Bjorn Helgaas <bhelgaas@google.com>
L1 PM Substates require the CLKREF# signal and may also require
device-specific support. If CLKREF# is not supported or driver support is
lacking, enabling L1.1 or L1.2 may cause errors when accessing devices,
e.g.,
nvme nvme0: controller is down; will reset: CSTS=0xffffffff, PCI_STATUS=0x10
If the kernel is built with CONFIG_PCIEASPM_POWER_SUPERSAVE=y or users
enable L1.x via sysfs, users may trip over these errors even if L1
Substates haven't been enabled by firmware or the driver.
To prevent such errors, disable advertising the L1 PM Substates unless the
driver sets "dw_pcie.l1ss_support" to indicate that it knows CLKREF# is
present and any device-specific configuration has been done.
Set "dw_pcie.l1ss_support" in tegra194 (if DT includes the
"supports-clkreq' property) and qcom (for 2.7.0 controllers) so they can
continue to use L1 Substates.
Based on Niklas's patch:
https://patch.msgid.link/20251017163252.598812-2-cassel@kernel.org
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
.../pci/controller/dwc/pcie-designware-ep.c | 2 ++
.../pci/controller/dwc/pcie-designware-host.c | 2 ++
drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++
drivers/pci/controller/dwc/pcie-designware.h | 2 ++
drivers/pci/controller/dwc/pcie-qcom.c | 2 ++
drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
6 files changed, 35 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 7f2112c2fb21..c94cff6eeb01 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -966,6 +966,8 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
if (ep->ops->init)
ep->ops->init(ep);
+ dw_pcie_config_l1ss(pci);
+
ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
/*
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 20c9333bcb1c..f1d5b45a3214 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
+ dw_pcie_config_l1ss(pci);
+
dw_pcie_config_presets(pp);
/*
* If the platform provides its own child bus config accesses, it means
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index c644216995f6..ede686623fad 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -1081,6 +1081,30 @@ void dw_pcie_edma_remove(struct dw_pcie *pci)
dw_edma_remove(&pci->edma);
}
+void dw_pcie_config_l1ss(struct dw_pcie *pci)
+{
+ u16 l1ss;
+ u32 l1ss_cap;
+
+ if (!pci->l1ss_support)
+ return;
+
+ l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
+ if (!l1ss)
+ return;
+
+ /*
+ * Unless the driver claims "l1ss_support", don't advertise L1 PM
+ * Substates because they require CLKREF# and possibly other
+ * device-specific configuration.
+ */
+ l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
+ l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
+ PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
+ PCI_L1SS_CAP_L1_PM_SS);
+ dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
+}
+
void dw_pcie_setup(struct dw_pcie *pci)
{
u32 val;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index e995f692a1ec..8d14b1fe2280 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -516,6 +516,7 @@ struct dw_pcie {
int max_link_speed;
u8 n_fts[2];
struct dw_edma_chip edma;
+ bool l1ss_support; /* L1 PM Substates support */
struct clk_bulk_data app_clks[DW_PCIE_NUM_APP_CLKS];
struct clk_bulk_data core_clks[DW_PCIE_NUM_CORE_CLKS];
struct reset_control_bulk_data app_rsts[DW_PCIE_NUM_APP_RSTS];
@@ -573,6 +574,7 @@ int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
int type, u64 parent_bus_addr,
u8 bar, size_t size);
void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
+void dw_pcie_config_l1ss(struct dw_pcie *pci);
void dw_pcie_setup(struct dw_pcie *pci);
void dw_pcie_iatu_detect(struct dw_pcie *pci);
int dw_pcie_edma_detect(struct dw_pcie *pci);
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 805edbbfe7eb..61c2f4e2f74d 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
val &= ~REQ_NOT_ENTR_L1;
writel(val, pcie->parf + PARF_PM_CTRL);
+ pci->l1ss_support = true;
+
val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
val |= EN;
writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 10e74458e667..3934757baa30 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -703,6 +703,9 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
val |= (pcie->aspm_pwr_on_t << 19);
dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val);
+ if (pcie->supports_clkreq)
+ pci->l1ss_support = true;
+
/* Program L0s and L1 entrance latencies */
val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK;
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-11 22:16 ` [PATCH 1/4] " Bjorn Helgaas
@ 2025-11-11 22:48 ` Frank Li
2025-11-11 23:07 ` Bjorn Helgaas
2025-11-12 1:03 ` Shawn Lin
2025-11-12 8:22 ` Niklas Cassel
2 siblings, 1 reply; 22+ messages in thread
From: Frank Li @ 2025-11-11 22:48 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Niklas Cassel, Shawn Lin, Manivannan Sadhasivam,
Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
Heiko Stuebner, Kever Yang, Simon Xue, Damien Le Moal,
Dragan Simic, FUKAUMI Naoki, Diederik de Haas, Richard Zhu,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas@google.com>
>
> L1 PM Substates require the CLKREF# signal and may also require
> device-specific support. If CLKREF# is not supported or driver support is
> lacking, enabling L1.1 or L1.2 may cause errors when accessing devices,
> e.g.,
>
> nvme nvme0: controller is down; will reset: CSTS=0xffffffff, PCI_STATUS=0x10
>
> If the kernel is built with CONFIG_PCIEASPM_POWER_SUPERSAVE=y or users
> enable L1.x via sysfs, users may trip over these errors even if L1
> Substates haven't been enabled by firmware or the driver.
>
> To prevent such errors, disable advertising the L1 PM Substates unless the
> driver sets "dw_pcie.l1ss_support" to indicate that it knows CLKREF# is
> present and any device-specific configuration has been done.
>
> Set "dw_pcie.l1ss_support" in tegra194 (if DT includes the
> "supports-clkreq' property) and qcom (for 2.7.0 controllers) so they can
> continue to use L1 Substates.
>
> Based on Niklas's patch:
> https://patch.msgid.link/20251017163252.598812-2-cassel@kernel.org
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> .../pci/controller/dwc/pcie-designware-ep.c | 2 ++
> .../pci/controller/dwc/pcie-designware-host.c | 2 ++
> drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++
> drivers/pci/controller/dwc/pcie-designware.h | 2 ++
> drivers/pci/controller/dwc/pcie-qcom.c | 2 ++
> drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
> 6 files changed, 35 insertions(+)
>
...
>
> +void dw_pcie_config_l1ss(struct dw_pcie *pci)
> +{
> + u16 l1ss;
> + u32 l1ss_cap;
> +
> + if (!pci->l1ss_support)
I think when l1ss_support true, need return.
when l1ss_support false, need clean PCI_L1SS_CAP.
Do your logic reverise?
Frank
> + return;
> +
> + l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
> + if (!l1ss)
> + return;
> +
> + /*
> + * Unless the driver claims "l1ss_support", don't advertise L1 PM
> + * Substates because they require CLKREF# and possibly other
> + * device-specific configuration.
> + */
> + l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> + l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
> + PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
> + PCI_L1SS_CAP_L1_PM_SS);
> + dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
> +}
> +
> void dw_pcie_setup(struct dw_pcie *pci)
> {
> u32 val;
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index e995f692a1ec..8d14b1fe2280 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -516,6 +516,7 @@ struct dw_pcie {
> int max_link_speed;
> u8 n_fts[2];
> struct dw_edma_chip edma;
> + bool l1ss_support; /* L1 PM Substates support */
> struct clk_bulk_data app_clks[DW_PCIE_NUM_APP_CLKS];
> struct clk_bulk_data core_clks[DW_PCIE_NUM_CORE_CLKS];
> struct reset_control_bulk_data app_rsts[DW_PCIE_NUM_APP_RSTS];
> @@ -573,6 +574,7 @@ int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> int type, u64 parent_bus_addr,
> u8 bar, size_t size);
> void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
> +void dw_pcie_config_l1ss(struct dw_pcie *pci);
> void dw_pcie_setup(struct dw_pcie *pci);
> void dw_pcie_iatu_detect(struct dw_pcie *pci);
> int dw_pcie_edma_detect(struct dw_pcie *pci);
> diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
> index 805edbbfe7eb..61c2f4e2f74d 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> val &= ~REQ_NOT_ENTR_L1;
> writel(val, pcie->parf + PARF_PM_CTRL);
>
> + pci->l1ss_support = true;
> +
> val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> val |= EN;
> writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 10e74458e667..3934757baa30 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -703,6 +703,9 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
> val |= (pcie->aspm_pwr_on_t << 19);
> dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val);
>
> + if (pcie->supports_clkreq)
> + pci->l1ss_support = true;
> +
> /* Program L0s and L1 entrance latencies */
> val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
> val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK;
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-11 22:48 ` Frank Li
@ 2025-11-11 23:07 ` Bjorn Helgaas
0 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-11 23:07 UTC (permalink / raw)
To: Frank Li
Cc: Niklas Cassel, Shawn Lin, Manivannan Sadhasivam,
Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
Heiko Stuebner, Kever Yang, Simon Xue, Damien Le Moal,
Dragan Simic, FUKAUMI Naoki, Diederik de Haas, Richard Zhu,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 11, 2025 at 05:48:07PM -0500, Frank Li wrote:
> On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> > From: Bjorn Helgaas <bhelgaas@google.com>
> >
> > L1 PM Substates require the CLKREF# signal and may also require
> > device-specific support. If CLKREF# is not supported or driver support is
> > lacking, enabling L1.1 or L1.2 may cause errors when accessing devices,
> > e.g.,
> >
> > nvme nvme0: controller is down; will reset: CSTS=0xffffffff, PCI_STATUS=0x10
> >
> > If the kernel is built with CONFIG_PCIEASPM_POWER_SUPERSAVE=y or users
> > enable L1.x via sysfs, users may trip over these errors even if L1
> > Substates haven't been enabled by firmware or the driver.
> >
> > To prevent such errors, disable advertising the L1 PM Substates unless the
> > driver sets "dw_pcie.l1ss_support" to indicate that it knows CLKREF# is
> > present and any device-specific configuration has been done.
> >
> > Set "dw_pcie.l1ss_support" in tegra194 (if DT includes the
> > "supports-clkreq' property) and qcom (for 2.7.0 controllers) so they can
> > continue to use L1 Substates.
> >
> > Based on Niklas's patch:
> > https://patch.msgid.link/20251017163252.598812-2-cassel@kernel.org
> >
> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > ---
> > .../pci/controller/dwc/pcie-designware-ep.c | 2 ++
> > .../pci/controller/dwc/pcie-designware-host.c | 2 ++
> > drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++
> > drivers/pci/controller/dwc/pcie-designware.h | 2 ++
> > drivers/pci/controller/dwc/pcie-qcom.c | 2 ++
> > drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
> > 6 files changed, 35 insertions(+)
> >
> ...
> >
> > +void dw_pcie_config_l1ss(struct dw_pcie *pci)
> > +{
> > + u16 l1ss;
> > + u32 l1ss_cap;
> > +
> > + if (!pci->l1ss_support)
>
> I think when l1ss_support true, need return.
> when l1ss_support false, need clean PCI_L1SS_CAP.
>
> Do your logic reverise?
Yes! Thank you, fixed locally.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-11 22:16 ` [PATCH 1/4] " Bjorn Helgaas
2025-11-11 22:48 ` Frank Li
@ 2025-11-12 1:03 ` Shawn Lin
2025-11-18 19:48 ` Bjorn Helgaas
2025-11-12 8:22 ` Niklas Cassel
2 siblings, 1 reply; 22+ messages in thread
From: Shawn Lin @ 2025-11-12 1:03 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: shawn.lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas, Niklas Cassel
在 2025/11/12 星期三 6:16, Bjorn Helgaas 写道:
> From: Bjorn Helgaas <bhelgaas@google.com>
>
> L1 PM Substates require the CLKREF# signal and may also require
> device-specific support. If CLKREF# is not supported or driver support is
> lacking, enabling L1.1 or L1.2 may cause errors when accessing devices,
> e.g.,
>
> nvme nvme0: controller is down; will reset: CSTS=0xffffffff, PCI_STATUS=0x10
>
> If the kernel is built with CONFIG_PCIEASPM_POWER_SUPERSAVE=y or users
> enable L1.x via sysfs, users may trip over these errors even if L1
> Substates haven't been enabled by firmware or the driver.
>
> To prevent such errors, disable advertising the L1 PM Substates unless the
> driver sets "dw_pcie.l1ss_support" to indicate that it knows CLKREF# is
> present and any device-specific configuration has been done.
>
> Set "dw_pcie.l1ss_support" in tegra194 (if DT includes the
> "supports-clkreq' property) and qcom (for 2.7.0 controllers) so they can
> continue to use L1 Substates.
>
> Based on Niklas's patch:
> https://patch.msgid.link/20251017163252.598812-2-cassel@kernel.org
Except the issue Fank pointed out, the commit msg says CLKREF# 3 times
which seems not a term from spec. Should it be CLKREQ# ?
Otherwise,
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> .../pci/controller/dwc/pcie-designware-ep.c | 2 ++
> .../pci/controller/dwc/pcie-designware-host.c | 2 ++
> drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++
> drivers/pci/controller/dwc/pcie-designware.h | 2 ++
> drivers/pci/controller/dwc/pcie-qcom.c | 2 ++
> drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
> 6 files changed, 35 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 7f2112c2fb21..c94cff6eeb01 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -966,6 +966,8 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> if (ep->ops->init)
> ep->ops->init(ep);
>
> + dw_pcie_config_l1ss(pci);
> +
> ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
>
> /*
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 20c9333bcb1c..f1d5b45a3214 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
>
> + dw_pcie_config_l1ss(pci);
> +
> dw_pcie_config_presets(pp);
> /*
> * If the platform provides its own child bus config accesses, it means
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index c644216995f6..ede686623fad 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -1081,6 +1081,30 @@ void dw_pcie_edma_remove(struct dw_pcie *pci)
> dw_edma_remove(&pci->edma);
> }
>
> +void dw_pcie_config_l1ss(struct dw_pcie *pci)
> +{
> + u16 l1ss;
> + u32 l1ss_cap;
> +
> + if (!pci->l1ss_support)
> + return;
> +
> + l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
> + if (!l1ss)
> + return;
> +
> + /*
> + * Unless the driver claims "l1ss_support", don't advertise L1 PM
> + * Substates because they require CLKREF# and possibly other
> + * device-specific configuration.
> + */
> + l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> + l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
> + PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
> + PCI_L1SS_CAP_L1_PM_SS);
> + dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
> +}
> +
> void dw_pcie_setup(struct dw_pcie *pci)
> {
> u32 val;
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index e995f692a1ec..8d14b1fe2280 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -516,6 +516,7 @@ struct dw_pcie {
> int max_link_speed;
> u8 n_fts[2];
> struct dw_edma_chip edma;
> + bool l1ss_support; /* L1 PM Substates support */
> struct clk_bulk_data app_clks[DW_PCIE_NUM_APP_CLKS];
> struct clk_bulk_data core_clks[DW_PCIE_NUM_CORE_CLKS];
> struct reset_control_bulk_data app_rsts[DW_PCIE_NUM_APP_RSTS];
> @@ -573,6 +574,7 @@ int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> int type, u64 parent_bus_addr,
> u8 bar, size_t size);
> void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
> +void dw_pcie_config_l1ss(struct dw_pcie *pci);
> void dw_pcie_setup(struct dw_pcie *pci);
> void dw_pcie_iatu_detect(struct dw_pcie *pci);
> int dw_pcie_edma_detect(struct dw_pcie *pci);
> diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
> index 805edbbfe7eb..61c2f4e2f74d 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> val &= ~REQ_NOT_ENTR_L1;
> writel(val, pcie->parf + PARF_PM_CTRL);
>
> + pci->l1ss_support = true;
> +
> val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> val |= EN;
> writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 10e74458e667..3934757baa30 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -703,6 +703,9 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
> val |= (pcie->aspm_pwr_on_t << 19);
> dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val);
>
> + if (pcie->supports_clkreq)
> + pci->l1ss_support = true;
> +
> /* Program L0s and L1 entrance latencies */
> val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
> val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK;
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-12 1:03 ` Shawn Lin
@ 2025-11-18 19:48 ` Bjorn Helgaas
0 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-18 19:48 UTC (permalink / raw)
To: Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas, Niklas Cassel
On Wed, Nov 12, 2025 at 09:03:38AM +0800, Shawn Lin wrote:
> 在 2025/11/12 星期三 6:16, Bjorn Helgaas 写道:
> > From: Bjorn Helgaas <bhelgaas@google.com>
> >
> > L1 PM Substates require the CLKREF# signal and may also require
> > device-specific support. If CLKREF# is not supported or driver support is
> > lacking, enabling L1.1 or L1.2 may cause errors when accessing devices,
> > e.g.,
> >
> > nvme nvme0: controller is down; will reset: CSTS=0xffffffff, PCI_STATUS=0x10
> >
> > If the kernel is built with CONFIG_PCIEASPM_POWER_SUPERSAVE=y or users
> > enable L1.x via sysfs, users may trip over these errors even if L1
> > Substates haven't been enabled by firmware or the driver.
> >
> > To prevent such errors, disable advertising the L1 PM Substates unless the
> > driver sets "dw_pcie.l1ss_support" to indicate that it knows CLKREF# is
> > present and any device-specific configuration has been done.
> >
> > Set "dw_pcie.l1ss_support" in tegra194 (if DT includes the
> > "supports-clkreq' property) and qcom (for 2.7.0 controllers) so they can
> > continue to use L1 Substates.
> >
> > Based on Niklas's patch:
> > https://patch.msgid.link/20251017163252.598812-2-cassel@kernel.org
>
>
> Except the issue Fank pointed out, the commit msg says CLKREF# 3 times
> which seems not a term from spec. Should it be CLKREQ# ?
Yes! Thank you, fixed locally.
> Otherwise,
> Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
>
> >
> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > ---
> > .../pci/controller/dwc/pcie-designware-ep.c | 2 ++
> > .../pci/controller/dwc/pcie-designware-host.c | 2 ++
> > drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++
> > drivers/pci/controller/dwc/pcie-designware.h | 2 ++
> > drivers/pci/controller/dwc/pcie-qcom.c | 2 ++
> > drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
> > 6 files changed, 35 insertions(+)
> >
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > index 7f2112c2fb21..c94cff6eeb01 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > @@ -966,6 +966,8 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
> > if (ep->ops->init)
> > ep->ops->init(ep);
> > + dw_pcie_config_l1ss(pci);
> > +
> > ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
> > /*
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > index 20c9333bcb1c..f1d5b45a3214 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> > PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> > dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
> > + dw_pcie_config_l1ss(pci);
> > +
> > dw_pcie_config_presets(pp);
> > /*
> > * If the platform provides its own child bus config accesses, it means
> > diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> > index c644216995f6..ede686623fad 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > @@ -1081,6 +1081,30 @@ void dw_pcie_edma_remove(struct dw_pcie *pci)
> > dw_edma_remove(&pci->edma);
> > }
> > +void dw_pcie_config_l1ss(struct dw_pcie *pci)
> > +{
> > + u16 l1ss;
> > + u32 l1ss_cap;
> > +
> > + if (!pci->l1ss_support)
> > + return;
> > +
> > + l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
> > + if (!l1ss)
> > + return;
> > +
> > + /*
> > + * Unless the driver claims "l1ss_support", don't advertise L1 PM
> > + * Substates because they require CLKREF# and possibly other
> > + * device-specific configuration.
> > + */
> > + l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> > + l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
> > + PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
> > + PCI_L1SS_CAP_L1_PM_SS);
> > + dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
> > +}
> > +
> > void dw_pcie_setup(struct dw_pcie *pci)
> > {
> > u32 val;
> > diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> > index e995f692a1ec..8d14b1fe2280 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware.h
> > +++ b/drivers/pci/controller/dwc/pcie-designware.h
> > @@ -516,6 +516,7 @@ struct dw_pcie {
> > int max_link_speed;
> > u8 n_fts[2];
> > struct dw_edma_chip edma;
> > + bool l1ss_support; /* L1 PM Substates support */
> > struct clk_bulk_data app_clks[DW_PCIE_NUM_APP_CLKS];
> > struct clk_bulk_data core_clks[DW_PCIE_NUM_CORE_CLKS];
> > struct reset_control_bulk_data app_rsts[DW_PCIE_NUM_APP_RSTS];
> > @@ -573,6 +574,7 @@ int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> > int type, u64 parent_bus_addr,
> > u8 bar, size_t size);
> > void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
> > +void dw_pcie_config_l1ss(struct dw_pcie *pci);
> > void dw_pcie_setup(struct dw_pcie *pci);
> > void dw_pcie_iatu_detect(struct dw_pcie *pci);
> > int dw_pcie_edma_detect(struct dw_pcie *pci);
> > diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
> > index 805edbbfe7eb..61c2f4e2f74d 100644
> > --- a/drivers/pci/controller/dwc/pcie-qcom.c
> > +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> > @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> > val &= ~REQ_NOT_ENTR_L1;
> > writel(val, pcie->parf + PARF_PM_CTRL);
> > + pci->l1ss_support = true;
> > +
> > val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> > val |= EN;
> > writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> > diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> > index 10e74458e667..3934757baa30 100644
> > --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> > +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> > @@ -703,6 +703,9 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
> > val |= (pcie->aspm_pwr_on_t << 19);
> > dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val);
> > + if (pcie->supports_clkreq)
> > + pci->l1ss_support = true;
> > +
> > /* Program L0s and L1 entrance latencies */
> > val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
> > val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK;
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-11 22:16 ` [PATCH 1/4] " Bjorn Helgaas
2025-11-11 22:48 ` Frank Li
2025-11-12 1:03 ` Shawn Lin
@ 2025-11-12 8:22 ` Niklas Cassel
2025-11-12 17:51 ` Manivannan Sadhasivam
2025-11-18 20:36 ` Bjorn Helgaas
2 siblings, 2 replies; 22+ messages in thread
From: Niklas Cassel @ 2025-11-12 8:22 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
>
> + dw_pcie_config_l1ss(pci);
The name dw_pcie_config_l1ss() sounds like we are enabling l1ss.
I know naming is hard.
Perhaps dw_pcie_disable_unsupported_l1ss() ?
Or something similar.
> --- a/drivers/pci/controller/dwc/pcie-qcom.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> val &= ~REQ_NOT_ENTR_L1;
> writel(val, pcie->parf + PARF_PM_CTRL);
>
> + pci->l1ss_support = true;
> +
> val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> val |= EN;
> writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
While it seems like ops_2_7_0 is the only type that explicitly does a
register write to enable L1ss, other versions might have the register
as enabled by default, so it would be nice if Mani could confirm exactly
which versions that should set l1ss_support = true.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-12 8:22 ` Niklas Cassel
@ 2025-11-12 17:51 ` Manivannan Sadhasivam
2025-11-18 20:22 ` Bjorn Helgaas
2025-11-18 20:36 ` Bjorn Helgaas
1 sibling, 1 reply; 22+ messages in thread
From: Manivannan Sadhasivam @ 2025-11-12 17:51 UTC (permalink / raw)
To: Niklas Cassel
Cc: Bjorn Helgaas, Shawn Lin, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Wed, Nov 12, 2025 at 09:22:36AM +0100, Niklas Cassel wrote:
> On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> > PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> > dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
> >
> > + dw_pcie_config_l1ss(pci);
>
> The name dw_pcie_config_l1ss() sounds like we are enabling l1ss.
>
> I know naming is hard.
>
> Perhaps dw_pcie_disable_unsupported_l1ss() ?
>
> Or something similar.
>
>
> > --- a/drivers/pci/controller/dwc/pcie-qcom.c
> > +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> > @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> > val &= ~REQ_NOT_ENTR_L1;
> > writel(val, pcie->parf + PARF_PM_CTRL);
> >
> > + pci->l1ss_support = true;
> > +
> > val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> > val |= EN;
> > writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
>
> While it seems like ops_2_7_0 is the only type that explicitly does a
> register write to enable L1ss, other versions might have the register
> as enabled by default, so it would be nice if Mani could confirm exactly
> which versions that should set l1ss_support = true.
>
Yes, on the rest of the platforms, this bit is supposed to be enabled by
default. AFAIK, all Qcom platforms should support L1SS, atleast the
non-IPQ/APQ ones.
We should set it for below cfgs:
cfg_fw_managed
cfg_sc8280xp
cfg_1_34_0
cfg_1_9_0
cfg_2_7_0
I excluded msm8996 due to one recent bug report.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-12 17:51 ` Manivannan Sadhasivam
@ 2025-11-18 20:22 ` Bjorn Helgaas
0 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-18 20:22 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Niklas Cassel, Shawn Lin, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Wed, Nov 12, 2025 at 11:21:07PM +0530, Manivannan Sadhasivam wrote:
> On Wed, Nov 12, 2025 at 09:22:36AM +0100, Niklas Cassel wrote:
> > On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> > > PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> > > dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
> > >
> > > + dw_pcie_config_l1ss(pci);
> > > --- a/drivers/pci/controller/dwc/pcie-qcom.c
> > > +++ b/drivers/pci/controller/dwc/pcie-qcom.c
> > > @@ -1067,6 +1067,8 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
> > > val &= ~REQ_NOT_ENTR_L1;
> > > writel(val, pcie->parf + PARF_PM_CTRL);
> > >
> > > + pci->l1ss_support = true;
> > > +
> > > val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> > > val |= EN;
> > > writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
> >
> > While it seems like ops_2_7_0 is the only type that explicitly does a
> > register write to enable L1ss, other versions might have the register
> > as enabled by default, so it would be nice if Mani could confirm exactly
> > which versions that should set l1ss_support = true.
> >
>
> Yes, on the rest of the platforms, this bit is supposed to be enabled by
> default. AFAIK, all Qcom platforms should support L1SS, atleast the
> non-IPQ/APQ ones.
>
> We should set it for below cfgs:
>
> cfg_fw_managed
> cfg_sc8280xp
> cfg_1_34_0
> cfg_1_9_0
> cfg_2_7_0
Except for cfg_fw_managed, the above are all covered by
qcom_pcie_init_2_7_0(), either via ops_2_7_0, ops_1_9_0, or
ops_1_21_0.
cfg_fw_managed is harder because we don't use dw_pcie_host_init() or
dw_pcie_setup_rc().
We do allocate a struct dw_pcie (where l1ss_support is) in
qcom_pcie_ecam_host_init(), but only so we can call
dw_pcie_msi_host_init() and dw_pcie_msi_init().
Neither of those seems like a logical place to fiddle with L1SS
support.
Open to suggestions.
Bjorn
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-12 8:22 ` Niklas Cassel
2025-11-12 17:51 ` Manivannan Sadhasivam
@ 2025-11-18 20:36 ` Bjorn Helgaas
2025-11-18 20:45 ` Niklas Cassel
1 sibling, 1 reply; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-18 20:36 UTC (permalink / raw)
To: Niklas Cassel
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Wed, Nov 12, 2025 at 09:22:36AM +0100, Niklas Cassel wrote:
> On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> > PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> > dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
> >
> > + dw_pcie_config_l1ss(pci);
>
> The name dw_pcie_config_l1ss() sounds like we are enabling l1ss.
>
> I know naming is hard.
>
> Perhaps dw_pcie_disable_unsupported_l1ss() ?
>
> Or something similar.
"disable" sounds like something we do with a control register, and
here we want to remove the advertised support from the capabilities
register.
Maybe dw_pcie_hide_unsupported_l1ss()?
Bjorn
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it
2025-11-18 20:36 ` Bjorn Helgaas
@ 2025-11-18 20:45 ` Niklas Cassel
0 siblings, 0 replies; 22+ messages in thread
From: Niklas Cassel @ 2025-11-18 20:45 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 18, 2025 at 02:36:38PM -0600, Bjorn Helgaas wrote:
> On Wed, Nov 12, 2025 at 09:22:36AM +0100, Niklas Cassel wrote:
> > On Tue, Nov 11, 2025 at 04:16:08PM -0600, Bjorn Helgaas wrote:
> > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -1060,6 +1060,8 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
> > > PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
> > > dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
> > >
> > > + dw_pcie_config_l1ss(pci);
> >
> > The name dw_pcie_config_l1ss() sounds like we are enabling l1ss.
> >
> > I know naming is hard.
> >
> > Perhaps dw_pcie_disable_unsupported_l1ss() ?
> >
> > Or something similar.
>
> "disable" sounds like something we do with a control register, and
> here we want to remove the advertised support from the capabilities
> register.
>
> Maybe dw_pcie_hide_unsupported_l1ss()?
Sounds good to me :)
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code
2025-11-11 22:16 [PATCH 0/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it Bjorn Helgaas
2025-11-11 22:16 ` [PATCH 1/4] " Bjorn Helgaas
@ 2025-11-11 22:16 ` Bjorn Helgaas
2025-11-12 8:29 ` Niklas Cassel
2025-11-11 22:16 ` [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support Bjorn Helgaas
2025-11-11 22:16 ` [PATCH 4/4] arm64: dts: rockchip: Add PCIe clkreq stuff for RK3588 EVB1 Bjorn Helgaas
3 siblings, 1 reply; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-11 22:16 UTC (permalink / raw)
To: Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
From: Bjorn Helgaas <bhelgaas@google.com>
The DWC core clears the L1 Substates Supported bits unless the driver sets
the "dw_pcie.l1ss_support" flag.
The tegra194 init_host_aspm() sets "dw_pcie.l1ss_support" if the platform
has the "supports-clkreq" DT property. If "supports-clkreq" is absent,
"dw_pcie.l1ss_support" is not set, and the DWC core will clear the L1
Substates Supported bits.
The tegra194 code to clear the L1 Substates Supported bits is unnecessary,
so remove it.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
drivers/pci/controller/dwc/pcie-tegra194.c | 32 ----------------------
1 file changed, 32 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 3934757baa30..d5545bf37f81 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -608,24 +608,6 @@ static struct pci_ops tegra_pci_ops = {
};
#if defined(CONFIG_PCIEASPM)
-static void disable_aspm_l11(struct tegra_pcie_dw *pcie)
-{
- u32 val;
-
- val = dw_pcie_readl_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub);
- val &= ~PCI_L1SS_CAP_ASPM_L1_1;
- dw_pcie_writel_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub, val);
-}
-
-static void disable_aspm_l12(struct tegra_pcie_dw *pcie)
-{
- u32 val;
-
- val = dw_pcie_readl_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub);
- val &= ~PCI_L1SS_CAP_ASPM_L1_2;
- dw_pcie_writel_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub, val);
-}
-
static inline u32 event_counter_prog(struct tegra_pcie_dw *pcie, u32 event)
{
u32 val;
@@ -729,8 +711,6 @@ static void init_debugfs(struct tegra_pcie_dw *pcie)
aspm_state_cnt);
}
#else
-static inline void disable_aspm_l12(struct tegra_pcie_dw *pcie) { return; }
-static inline void disable_aspm_l11(struct tegra_pcie_dw *pcie) { return; }
static inline void init_host_aspm(struct tegra_pcie_dw *pcie) { return; }
static inline void init_debugfs(struct tegra_pcie_dw *pcie) { return; }
#endif
@@ -934,12 +914,6 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
init_host_aspm(pcie);
- /* Disable ASPM-L1SS advertisement if there is no CLKREQ routing */
- if (!pcie->supports_clkreq) {
- disable_aspm_l11(pcie);
- disable_aspm_l12(pcie);
- }
-
if (!pcie->of_data->has_l1ss_exit_fix) {
val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
@@ -1874,12 +1848,6 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
init_host_aspm(pcie);
- /* Disable ASPM-L1SS advertisement if there is no CLKREQ routing */
- if (!pcie->supports_clkreq) {
- disable_aspm_l11(pcie);
- disable_aspm_l12(pcie);
- }
-
if (!pcie->of_data->has_l1ss_exit_fix) {
val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code
2025-11-11 22:16 ` [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code Bjorn Helgaas
@ 2025-11-12 8:29 ` Niklas Cassel
2025-11-18 18:59 ` Bjorn Helgaas
0 siblings, 1 reply; 22+ messages in thread
From: Niklas Cassel @ 2025-11-12 8:29 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 11, 2025 at 04:16:09PM -0600, Bjorn Helgaas wrote:
> From: Bjorn Helgaas <bhelgaas@google.com>
>
> The DWC core clears the L1 Substates Supported bits unless the driver sets
> the "dw_pcie.l1ss_support" flag.
>
> The tegra194 init_host_aspm() sets "dw_pcie.l1ss_support" if the platform
> has the "supports-clkreq" DT property. If "supports-clkreq" is absent,
> "dw_pcie.l1ss_support" is not set, and the DWC core will clear the L1
> Substates Supported bits.
>
> The tegra194 code to clear the L1 Substates Supported bits is unnecessary,
> so remove it.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
Since init_host_aspm() is now the only place using struct tegra_pcie_dw
struct member cfg_link_cap_l1sub, I think that you can remove this struct
member, and instead make this a local variable in init_host_aspm().
Other than that, looks good to me:
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code
2025-11-12 8:29 ` Niklas Cassel
@ 2025-11-18 18:59 ` Bjorn Helgaas
2025-11-18 20:06 ` Niklas Cassel
0 siblings, 1 reply; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-18 18:59 UTC (permalink / raw)
To: Niklas Cassel
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Wed, Nov 12, 2025 at 09:29:20AM +0100, Niklas Cassel wrote:
> On Tue, Nov 11, 2025 at 04:16:09PM -0600, Bjorn Helgaas wrote:
> > From: Bjorn Helgaas <bhelgaas@google.com>
> >
> > The DWC core clears the L1 Substates Supported bits unless the driver sets
> > the "dw_pcie.l1ss_support" flag.
> >
> > The tegra194 init_host_aspm() sets "dw_pcie.l1ss_support" if the platform
> > has the "supports-clkreq" DT property. If "supports-clkreq" is absent,
> > "dw_pcie.l1ss_support" is not set, and the DWC core will clear the L1
> > Substates Supported bits.
> >
> > The tegra194 code to clear the L1 Substates Supported bits is unnecessary,
> > so remove it.
> >
> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > ---
>
> Since init_host_aspm() is now the only place using struct tegra_pcie_dw
> struct member cfg_link_cap_l1sub, I think that you can remove this struct
> member, and instead make this a local variable in init_host_aspm().
It looks like tegra_pcie_ep_irq_thread() also uses it, although I'm
dubious about that.
It's odd that software would be responsible for sending LTR messages,
but I guess this only happens for tegra194_pcie_dw_ep_of_data, and
apparently it's fixed (".has_ltr_req_fix" for tegra234.
And odd that we would read the capability register on every interrupt
even though this driver is the only thing that can change it, so we
should be able to cache the value in init_host_aspm().
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code
2025-11-18 18:59 ` Bjorn Helgaas
@ 2025-11-18 20:06 ` Niklas Cassel
2025-11-18 20:31 ` Bjorn Helgaas
0 siblings, 1 reply; 22+ messages in thread
From: Niklas Cassel @ 2025-11-18 20:06 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 18, 2025 at 12:59:17PM -0600, Bjorn Helgaas wrote:
> On Wed, Nov 12, 2025 at 09:29:20AM +0100, Niklas Cassel wrote:
> > On Tue, Nov 11, 2025 at 04:16:09PM -0600, Bjorn Helgaas wrote:
> > > From: Bjorn Helgaas <bhelgaas@google.com>
> > >
> > > The DWC core clears the L1 Substates Supported bits unless the driver sets
> > > the "dw_pcie.l1ss_support" flag.
> > >
> > > The tegra194 init_host_aspm() sets "dw_pcie.l1ss_support" if the platform
> > > has the "supports-clkreq" DT property. If "supports-clkreq" is absent,
> > > "dw_pcie.l1ss_support" is not set, and the DWC core will clear the L1
> > > Substates Supported bits.
> > >
> > > The tegra194 code to clear the L1 Substates Supported bits is unnecessary,
> > > so remove it.
> > >
> > > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > > ---
> >
> > Since init_host_aspm() is now the only place using struct tegra_pcie_dw
> > struct member cfg_link_cap_l1sub, I think that you can remove this struct
> > member, and instead make this a local variable in init_host_aspm().
>
> It looks like tegra_pcie_ep_irq_thread() also uses it, although I'm
> dubious about that.
>
> It's odd that software would be responsible for sending LTR messages,
> but I guess this only happens for tegra194_pcie_dw_ep_of_data, and
> apparently it's fixed (".has_ltr_req_fix" for tegra234.
>
> And odd that we would read the capability register on every interrupt
> even though this driver is the only thing that can change it, so we
> should be able to cache the value in init_host_aspm().
Yes, sorry, my thinking was that this code in tegra_pcie_ep_irq_thread():
/* If EP doesn't advertise L1SS, just return */
val = dw_pcie_readl_dbi(pci, pcie->cfg_link_cap_l1sub);
if (!(val & (PCI_L1SS_CAP_ASPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_2)))
return IRQ_HANDLED;
after your patch can be replaced with:
/* If EP doesn't advertise L1SS, just return */
if (!pci->l1ss_support)
return IRQ_HANDLED;
Since we already know that if !pci->l1ss_support,
these bits will be cleared by DWC common code.
So, after that, we could replace the struct tegra_pcie_dw
struct member cfg_link_cap_l1sub with a local variable in
init_host_aspm().
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code
2025-11-18 20:06 ` Niklas Cassel
@ 2025-11-18 20:31 ` Bjorn Helgaas
0 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-18 20:31 UTC (permalink / raw)
To: Niklas Cassel
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 18, 2025 at 09:06:08PM +0100, Niklas Cassel wrote:
> On Tue, Nov 18, 2025 at 12:59:17PM -0600, Bjorn Helgaas wrote:
> > On Wed, Nov 12, 2025 at 09:29:20AM +0100, Niklas Cassel wrote:
> > > On Tue, Nov 11, 2025 at 04:16:09PM -0600, Bjorn Helgaas wrote:
> > > > From: Bjorn Helgaas <bhelgaas@google.com>
> > > >
> > > > The DWC core clears the L1 Substates Supported bits unless the driver sets
> > > > the "dw_pcie.l1ss_support" flag.
> > > >
> > > > The tegra194 init_host_aspm() sets "dw_pcie.l1ss_support" if the platform
> > > > has the "supports-clkreq" DT property. If "supports-clkreq" is absent,
> > > > "dw_pcie.l1ss_support" is not set, and the DWC core will clear the L1
> > > > Substates Supported bits.
> > > >
> > > > The tegra194 code to clear the L1 Substates Supported bits is unnecessary,
> > > > so remove it.
> > > >
> > > > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > > > ---
> > >
> > > Since init_host_aspm() is now the only place using struct tegra_pcie_dw
> > > struct member cfg_link_cap_l1sub, I think that you can remove this struct
> > > member, and instead make this a local variable in init_host_aspm().
> >
> > It looks like tegra_pcie_ep_irq_thread() also uses it, although I'm
> > dubious about that.
> >
> > It's odd that software would be responsible for sending LTR messages,
> > but I guess this only happens for tegra194_pcie_dw_ep_of_data, and
> > apparently it's fixed (".has_ltr_req_fix" for tegra234.
> >
> > And odd that we would read the capability register on every interrupt
> > even though this driver is the only thing that can change it, so we
> > should be able to cache the value in init_host_aspm().
>
> Yes, sorry, my thinking was that this code in tegra_pcie_ep_irq_thread():
>
> /* If EP doesn't advertise L1SS, just return */
> val = dw_pcie_readl_dbi(pci, pcie->cfg_link_cap_l1sub);
> if (!(val & (PCI_L1SS_CAP_ASPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_2)))
> return IRQ_HANDLED;
>
>
> after your patch can be replaced with:
>
> /* If EP doesn't advertise L1SS, just return */
> if (!pci->l1ss_support)
> return IRQ_HANDLED;
>
>
> Since we already know that if !pci->l1ss_support,
> these bits will be cleared by DWC common code.
>
>
> So, after that, we could replace the struct tegra_pcie_dw
> struct member cfg_link_cap_l1sub with a local variable in
> init_host_aspm().
Oh, of course, thanks!
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support
2025-11-11 22:16 [PATCH 0/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it Bjorn Helgaas
2025-11-11 22:16 ` [PATCH 1/4] " Bjorn Helgaas
2025-11-11 22:16 ` [PATCH 2/4] PCI: tegra194: Remove unnecessary L1SS disable code Bjorn Helgaas
@ 2025-11-11 22:16 ` Bjorn Helgaas
2025-11-12 2:49 ` Hans Zhang
` (2 more replies)
2025-11-11 22:16 ` [PATCH 4/4] arm64: dts: rockchip: Add PCIe clkreq stuff for RK3588 EVB1 Bjorn Helgaas
3 siblings, 3 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-11 22:16 UTC (permalink / raw)
To: Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
From: Shawn Lin <shawn.lin@rock-chips.com>
L1 PM Substates for RC mode require support in the dw-rockchip driver
including proper handling of the CLKREQ# sideband signal. It is mostly
handled by hardware, but software still needs to set the clkreq fields
in the PCIE_CLIENT_POWER_CON register to match the hardware implementation.
For more details, see section '18.6.6.4 L1 Substate' in the RK3658 TRM 1.1
Part 2, or section '11.6.6.4 L1 Substate' in the RK3588 TRM 1.0 Part2.
Meanwhile, for the EP mode, we haven't prepared enough to actually support
L1 PM Substates yet. So disable it now until proper support is added later.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
[bhelgaas: set pci->l1ss_support so DWC core preserves L1SS Capability bits;
drop corresponding code here]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/1761187883-150120-1-git-send-email-shawn.lin@rock-chips.com
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 3e2752c7dd09..62a095752833 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -62,6 +62,12 @@
/* Interrupt Mask Register Related to Miscellaneous Operation */
#define PCIE_CLIENT_INTR_MASK_MISC 0x24
+/* Power Management Control Register */
+#define PCIE_CLIENT_POWER_CON 0x2c
+#define PCIE_CLKREQ_READY FIELD_PREP_WM16(BIT(0), 1)
+#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
+#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)
+
/* Hot Reset Control Register */
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
#define PCIE_LTSSM_APP_DLY2_EN BIT(1)
@@ -85,6 +91,7 @@ struct rockchip_pcie {
struct regulator *vpcie3v3;
struct irq_domain *irq_domain;
const struct rockchip_pcie_of_data *data;
+ bool supports_clkreq;
};
struct rockchip_pcie_of_data {
@@ -200,6 +207,32 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
}
+/*
+ * See e.g. section '11.6.6.4 L1 Substate' in the RK3588 TRM V1.0 for the steps
+ * needed to support L1 substates. Currently, just enable L1 substates for RC
+ * mode if CLKREQ# is properly connected and supports-clkreq is present in DT.
+ * For EP mode, there are more things should be done to actually save power in
+ * L1 substates, so disable L1 substates until there is proper support.
+ */
+static void rockchip_pcie_configure_l1sub(struct dw_pcie *pci)
+{
+ struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+
+ /* Enable L1 substates if CLKREQ# is properly connected */
+ if (rockchip->supports_clkreq &&
+ rockchip->data->mode == DW_PCIE_RC_TYPE ) {
+ rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY,
+ PCIE_CLIENT_POWER_CON);
+ pci->l1ss_support = true;
+ return;
+ }
+
+ /* Otherwise, pull down CLKREQ# */
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
+ PCIE_CLIENT_POWER_CON);
+}
+
static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
{
u32 cap, lnkcap;
@@ -264,6 +297,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
rockchip);
+ rockchip_pcie_configure_l1sub(pci);
rockchip_pcie_enable_l0s(pci);
return 0;
@@ -301,6 +335,7 @@ static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
enum pci_barno bar;
+ rockchip_pcie_configure_l1sub(pci);
rockchip_pcie_enable_l0s(pci);
rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
@@ -412,6 +447,9 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst),
"failed to get reset lines\n");
+ rockchip->supports_clkreq = of_property_read_bool(pdev->dev.of_node,
+ "supports-clkreq");
+
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support
2025-11-11 22:16 ` [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support Bjorn Helgaas
@ 2025-11-12 2:49 ` Hans Zhang
2025-11-12 8:30 ` Diederik de Haas
2025-11-12 8:36 ` Niklas Cassel
2 siblings, 0 replies; 22+ messages in thread
From: Hans Zhang @ 2025-11-12 2:49 UTC (permalink / raw)
To: Bjorn Helgaas, Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, linux-tegra,
linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On 11/12/2025 6:16 AM, Bjorn Helgaas wrote:
> EXTERNAL EMAIL
>
> From: Shawn Lin <shawn.lin@rock-chips.com>
>
> L1 PM Substates for RC mode require support in the dw-rockchip driver
> including proper handling of the CLKREQ# sideband signal. It is mostly
> handled by hardware, but software still needs to set the clkreq fields
> in the PCIE_CLIENT_POWER_CON register to match the hardware implementation.
>
> For more details, see section '18.6.6.4 L1 Substate' in the RK3658 TRM 1.1
> Part 2, or section '11.6.6.4 L1 Substate' in the RK3588 TRM 1.0 Part2.
>
> Meanwhile, for the EP mode, we haven't prepared enough to actually support
> L1 PM Substates yet. So disable it now until proper support is added later.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> [bhelgaas: set pci->l1ss_support so DWC core preserves L1SS Capability bits;
> drop corresponding code here]
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Link: https://patch.msgid.link/1761187883-150120-1-git-send-email-shawn.lin@rock-chips.com
Reviewed-by: Hans Zhang <hans.zhang@cixtech.com>
Best regards,
Hans
> ---
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 38 +++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 3e2752c7dd09..62a095752833 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -62,6 +62,12 @@
> /* Interrupt Mask Register Related to Miscellaneous Operation */
> #define PCIE_CLIENT_INTR_MASK_MISC 0x24
>
> +/* Power Management Control Register */
> +#define PCIE_CLIENT_POWER_CON 0x2c
> +#define PCIE_CLKREQ_READY FIELD_PREP_WM16(BIT(0), 1)
> +#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
> +#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)
> +
> /* Hot Reset Control Register */
> #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
> #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
> @@ -85,6 +91,7 @@ struct rockchip_pcie {
> struct regulator *vpcie3v3;
> struct irq_domain *irq_domain;
> const struct rockchip_pcie_of_data *data;
> + bool supports_clkreq;
> };
>
> struct rockchip_pcie_of_data {
> @@ -200,6 +207,32 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
> return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
> }
>
> +/*
> + * See e.g. section '11.6.6.4 L1 Substate' in the RK3588 TRM V1.0 for the steps
> + * needed to support L1 substates. Currently, just enable L1 substates for RC
> + * mode if CLKREQ# is properly connected and supports-clkreq is present in DT.
> + * For EP mode, there are more things should be done to actually save power in
> + * L1 substates, so disable L1 substates until there is proper support.
> + */
> +static void rockchip_pcie_configure_l1sub(struct dw_pcie *pci)
> +{
> + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
> +
> + /* Enable L1 substates if CLKREQ# is properly connected */
> + if (rockchip->supports_clkreq &&
> + rockchip->data->mode == DW_PCIE_RC_TYPE ) {
> + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY,
> + PCIE_CLIENT_POWER_CON);
> + pci->l1ss_support = true;
> + return;
> + }
> +
> + /* Otherwise, pull down CLKREQ# */
> + rockchip_pcie_writel_apb(rockchip,
> + PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
> + PCIE_CLIENT_POWER_CON);
> +}
> +
> static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
> {
> u32 cap, lnkcap;
> @@ -264,6 +297,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
> irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
> rockchip);
>
> + rockchip_pcie_configure_l1sub(pci);
> rockchip_pcie_enable_l0s(pci);
>
> return 0;
> @@ -301,6 +335,7 @@ static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> enum pci_barno bar;
>
> + rockchip_pcie_configure_l1sub(pci);
> rockchip_pcie_enable_l0s(pci);
> rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
>
> @@ -412,6 +447,9 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
> return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst),
> "failed to get reset lines\n");
>
> + rockchip->supports_clkreq = of_property_read_bool(pdev->dev.of_node,
> + "supports-clkreq");
> +
> return 0;
> }
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support
2025-11-11 22:16 ` [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support Bjorn Helgaas
2025-11-12 2:49 ` Hans Zhang
@ 2025-11-12 8:30 ` Diederik de Haas
2025-11-12 8:36 ` Niklas Cassel
2 siblings, 0 replies; 22+ messages in thread
From: Diederik de Haas @ 2025-11-12 8:30 UTC (permalink / raw)
To: Bjorn Helgaas, Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue Nov 11, 2025 at 11:16 PM CET, Bjorn Helgaas wrote:
> From: Shawn Lin <shawn.lin@rock-chips.com>
>
> L1 PM Substates for RC mode require support in the dw-rockchip driver
> including proper handling of the CLKREQ# sideband signal. It is mostly
> handled by hardware, but software still needs to set the clkreq fields
> in the PCIE_CLIENT_POWER_CON register to match the hardware implementation.
>
> For more details, see section '18.6.6.4 L1 Substate' in the RK3658 TRM 1.1
s/RK3658/RK3568/
Sorry,
Diederik
> Part 2, or section '11.6.6.4 L1 Substate' in the RK3588 TRM 1.0 Part2.
>
> Meanwhile, for the EP mode, we haven't prepared enough to actually support
> L1 PM Substates yet. So disable it now until proper support is added later.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> [bhelgaas: set pci->l1ss_support so DWC core preserves L1SS Capability bits;
> drop corresponding code here]
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Link: https://patch.msgid.link/1761187883-150120-1-git-send-email-shawn.lin@rock-chips.com
> ---
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 38 +++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 3e2752c7dd09..62a095752833 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -62,6 +62,12 @@
> /* Interrupt Mask Register Related to Miscellaneous Operation */
> #define PCIE_CLIENT_INTR_MASK_MISC 0x24
>
> +/* Power Management Control Register */
> +#define PCIE_CLIENT_POWER_CON 0x2c
> +#define PCIE_CLKREQ_READY FIELD_PREP_WM16(BIT(0), 1)
> +#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
> +#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)
> +
> /* Hot Reset Control Register */
> #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
> #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
> @@ -85,6 +91,7 @@ struct rockchip_pcie {
> struct regulator *vpcie3v3;
> struct irq_domain *irq_domain;
> const struct rockchip_pcie_of_data *data;
> + bool supports_clkreq;
> };
>
> struct rockchip_pcie_of_data {
> @@ -200,6 +207,32 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
> return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
> }
>
> +/*
> + * See e.g. section '11.6.6.4 L1 Substate' in the RK3588 TRM V1.0 for the steps
> + * needed to support L1 substates. Currently, just enable L1 substates for RC
> + * mode if CLKREQ# is properly connected and supports-clkreq is present in DT.
> + * For EP mode, there are more things should be done to actually save power in
> + * L1 substates, so disable L1 substates until there is proper support.
> + */
> +static void rockchip_pcie_configure_l1sub(struct dw_pcie *pci)
> +{
> + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
> +
> + /* Enable L1 substates if CLKREQ# is properly connected */
> + if (rockchip->supports_clkreq &&
> + rockchip->data->mode == DW_PCIE_RC_TYPE ) {
> + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY,
> + PCIE_CLIENT_POWER_CON);
> + pci->l1ss_support = true;
> + return;
> + }
> +
> + /* Otherwise, pull down CLKREQ# */
> + rockchip_pcie_writel_apb(rockchip,
> + PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
> + PCIE_CLIENT_POWER_CON);
> +}
> +
> static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
> {
> u32 cap, lnkcap;
> @@ -264,6 +297,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
> irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
> rockchip);
>
> + rockchip_pcie_configure_l1sub(pci);
> rockchip_pcie_enable_l0s(pci);
>
> return 0;
> @@ -301,6 +335,7 @@ static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> enum pci_barno bar;
>
> + rockchip_pcie_configure_l1sub(pci);
> rockchip_pcie_enable_l0s(pci);
> rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
>
> @@ -412,6 +447,9 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
> return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst),
> "failed to get reset lines\n");
>
> + rockchip->supports_clkreq = of_property_read_bool(pdev->dev.of_node,
> + "supports-clkreq");
> +
> return 0;
> }
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support
2025-11-11 22:16 ` [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support Bjorn Helgaas
2025-11-12 2:49 ` Hans Zhang
2025-11-12 8:30 ` Diederik de Haas
@ 2025-11-12 8:36 ` Niklas Cassel
2 siblings, 0 replies; 22+ messages in thread
From: Niklas Cassel @ 2025-11-12 8:36 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Shawn Lin, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
On Tue, Nov 11, 2025 at 04:16:10PM -0600, Bjorn Helgaas wrote:
> From: Shawn Lin <shawn.lin@rock-chips.com>
>
> L1 PM Substates for RC mode require support in the dw-rockchip driver
> including proper handling of the CLKREQ# sideband signal. It is mostly
> handled by hardware, but software still needs to set the clkreq fields
> in the PCIE_CLIENT_POWER_CON register to match the hardware implementation.
>
> For more details, see section '18.6.6.4 L1 Substate' in the RK3658 TRM 1.1
> Part 2, or section '11.6.6.4 L1 Substate' in the RK3588 TRM 1.0 Part2.
>
> Meanwhile, for the EP mode, we haven't prepared enough to actually support
> L1 PM Substates yet. So disable it now until proper support is added later.
Considering that patch 1/4 is disabling L1ss for EP mode, I think we can
remove this last sentence.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> [bhelgaas: set pci->l1ss_support so DWC core preserves L1SS Capability bits;
> drop corresponding code here]
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Link: https://patch.msgid.link/1761187883-150120-1-git-send-email-shawn.lin@rock-chips.com
> ---
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 38 +++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 3e2752c7dd09..62a095752833 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -62,6 +62,12 @@
> /* Interrupt Mask Register Related to Miscellaneous Operation */
> #define PCIE_CLIENT_INTR_MASK_MISC 0x24
>
> +/* Power Management Control Register */
> +#define PCIE_CLIENT_POWER_CON 0x2c
> +#define PCIE_CLKREQ_READY FIELD_PREP_WM16(BIT(0), 1)
> +#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
> +#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)
> +
> /* Hot Reset Control Register */
> #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
> #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
> @@ -85,6 +91,7 @@ struct rockchip_pcie {
> struct regulator *vpcie3v3;
> struct irq_domain *irq_domain;
> const struct rockchip_pcie_of_data *data;
> + bool supports_clkreq;
> };
>
> struct rockchip_pcie_of_data {
> @@ -200,6 +207,32 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
> return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
> }
>
> +/*
> + * See e.g. section '11.6.6.4 L1 Substate' in the RK3588 TRM V1.0 for the steps
> + * needed to support L1 substates. Currently, just enable L1 substates for RC
> + * mode if CLKREQ# is properly connected and supports-clkreq is present in DT.
> + * For EP mode, there are more things should be done to actually save power in
> + * L1 substates, so disable L1 substates until there is proper support.
> + */
> +static void rockchip_pcie_configure_l1sub(struct dw_pcie *pci)
> +{
> + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
> +
> + /* Enable L1 substates if CLKREQ# is properly connected */
> + if (rockchip->supports_clkreq &&
> + rockchip->data->mode == DW_PCIE_RC_TYPE ) {
Superfluous space before '('
Considering that DWC core clears L1ss cap, and according to Shawn, there
is more code needed to support L1ss in EP mode, perhaps simply drop the
function call from rockchip_pcie_ep_init(), then we can drop
'rockchip->data->mode == DW_PCIE_RC_TYPE' from the above if statement.
> + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY,
> + PCIE_CLIENT_POWER_CON);
> + pci->l1ss_support = true;
> + return;
> + }
> +
> + /* Otherwise, pull down CLKREQ# */
> + rockchip_pcie_writel_apb(rockchip,
> + PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
> + PCIE_CLIENT_POWER_CON);
> +}
> +
> static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
> {
> u32 cap, lnkcap;
> @@ -264,6 +297,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
> irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
> rockchip);
>
> + rockchip_pcie_configure_l1sub(pci);
> rockchip_pcie_enable_l0s(pci);
>
> return 0;
> @@ -301,6 +335,7 @@ static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> enum pci_barno bar;
>
> + rockchip_pcie_configure_l1sub(pci);
Considering that DWC core clears L1ss cap, and according to Shawn, there
is more code needed to support L1ss in EP mode, perhaps simply drop this
function call?
> rockchip_pcie_enable_l0s(pci);
> rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep);
>
> @@ -412,6 +447,9 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
> return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst),
> "failed to get reset lines\n");
>
> + rockchip->supports_clkreq = of_property_read_bool(pdev->dev.of_node,
> + "supports-clkreq");
> +
> return 0;
> }
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 4/4] arm64: dts: rockchip: Add PCIe clkreq stuff for RK3588 EVB1
2025-11-11 22:16 [PATCH 0/4] PCI: dwc: Advertise L1 PM Substates only if driver requests it Bjorn Helgaas
` (2 preceding siblings ...)
2025-11-11 22:16 ` [PATCH 3/4] PCI: dw-rockchip: Configure L1sub support Bjorn Helgaas
@ 2025-11-11 22:16 ` Bjorn Helgaas
3 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2025-11-11 22:16 UTC (permalink / raw)
To: Niklas Cassel, Shawn Lin
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Heiko Stuebner,
Kever Yang, Simon Xue, Damien Le Moal, Dragan Simic,
FUKAUMI Naoki, Diederik de Haas, Richard Zhu, Frank Li,
Lucas Stach, Shawn Guo, Sascha Hauer, Fabio Estevam, Conor Dooley,
Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Hans Zhang,
linux-tegra, linux-pci, linux-arm-kernel, linux-rockchip, kernel,
Bjorn Helgaas
From: Shawn Lin <shawn.lin@rock-chips.com>
Add supports-clkreq and pinmux for PCIe ASPM L1 substates.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Hans Zhang <hans.zhang@cixtech.com>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/1761187883-150120-2-git-send-email-shawn.lin@rock-chips.com
---
arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index ff1ba5ed56ef..c9d284cb738b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -522,6 +522,7 @@ &pcie2x1l0 {
pinctrl-names = "default";
pinctrl-0 = <&pcie2_0_rst>, <&pcie2_0_wake>, <&pcie2_0_clkreq>, <&wifi_host_wake_irq>;
reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ supports-clkreq;
vpcie3v3-supply = <&vcc3v3_wlan>;
status = "okay";
@@ -545,7 +546,8 @@ wifi: wifi@0,0 {
&pcie2x1l1 {
reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
- pinctrl-0 = <&pcie2_1_rst>, <&rtl8111_isolate>;
+ pinctrl-0 = <&pcie2_1_rst>, <&rtl8111_isolate>, <&pcie30x1m1_1_clkreqn>;
+ supports-clkreq;
status = "okay";
};
@@ -555,7 +557,8 @@ &pcie30phy {
&pcie3x4 {
pinctrl-names = "default";
- pinctrl-0 = <&pcie3_reset>;
+ pinctrl-0 = <&pcie3_reset>, <&pcie30x4m1_clkreqn>;
+ supports-clkreq;
reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie30>;
status = "okay";
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread