[PATCH v2 1/2] PCI: dw-rockchip: Add L1sub support
Manivannan Sadhasivam
mani at kernel.org
Wed Oct 22 09:03:09 PDT 2025
On Wed, Oct 22, 2025 at 10:27:39PM +0800, Shawn Lin wrote:
>
> 在 2025/10/22 星期三 21:04, Manivannan Sadhasivam 写道:
> > On Wed, Oct 22, 2025 at 07:35:53PM +0800, Shawn Lin wrote:
> > > The driver should set app_clk_req_n(clkreq ready) of PCIE_CLIENT_POWER reg
> > > to support L1sub. Otherwise, unset app_clk_req_n and pull down CLKREQ#.
> > >
> >
> > You can definitely improve the commit message on explaining why L1 PM Substates
> > need to be disabled when the DT property is not present etc... Please refer the
> > patch from Niklas.
>
> Will do.
>
> >
> > > Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> > >
> > > ---
> > >
> > > Changes in v2:
> > > - drop of_pci_clkreq_presnt API
> > > - drop dependency of Niklas's patch
> > >
> > > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 36 +++++++++++++++++++++++++++
> > > 1 file changed, 36 insertions(+)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > > index 3e2752c..18cd626 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 0x2c
> > > +#define PCIE_CLKREQ_READY 0x10001
> > > +#define PCIE_CLKREQ_NOT_READY 0x10000
> > > +#define PCIE_CLKREQ_PULL_DOWN 0x30001000
> >
> > Can you use bitfields instead of magic values?
>
> Of course, will fix.
>
> >
> > > +
> > > /* 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,31 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
> > > return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
> > > }
> > > +static void rockchip_pcie_enable_l1sub(struct dw_pcie *pci)
> >
> > rockchip_pcie_configure_l1sub()? since this function is not just enabling L1ss.
> >
> > > +{
> > > + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
> > > + u32 cap, l1subcap;
> > > +
> > > + /* Enable L1 substates if CLKREQ# is properly connected */
> > > + if (rockchip->supports_clkreq) {
> > > + /* Ready to have reference clock removed */
> >
> > This comment is misleading (maybe wrong). The presence of this property implies
> > that the link could enter L1 PM Substates. REFCLK removal only happens when the
> > link is in L1ss.
> >
> > So drop the comment.
>
> Will drop.
>
> >
> > > + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY, PCIE_CLIENT_POWER);
> > > + return;
> > > + }
> > > +
> > > + /* Otherwise, pull down CLKREQ# and disable L1 substates */
> >
> > "L1 PM Substates"
> >
> > > + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
> > > + PCIE_CLIENT_POWER);
> > > + cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
> > > + if (cap) {
> > > + l1subcap = dw_pcie_readl_dbi(pci, cap + PCI_L1SS_CAP);
> > > + l1subcap &= ~(PCI_L1SS_CAP_L1_PM_SS | PCI_L1SS_CAP_ASPM_L1_1 |
> > > + PCI_L1SS_CAP_ASPM_L1_2 | PCI_L1SS_CAP_PCIPM_L1_1 |
> > > + PCI_L1SS_CAP_PCIPM_L1_2);
> > > + dw_pcie_writel_dbi(pci, cap + PCI_L1SS_CAP, l1subcap);
> > > + }
> > > +}
> > > +
> > > static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
> > > {
> > > u32 cap, lnkcap;
> > > @@ -264,6 +296,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_enable_l1sub(pci);
> > > rockchip_pcie_enable_l0s(pci);
> > > return 0;
> > > @@ -301,6 +334,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_enable_l1sub(pci);
> >
> > I don't think you can decide the CLKREQ# routing on the EP side. The
> > 'supports-clkreq' property is meant only for the RC afaik.
>
> You are right, we cannot decide the CLKREQ# routing on the EP side. But
> what I have in mind is we at least need to set pinmux to CLKREQ function
> because on Rockchip platforms, the CLKREQ# of EP mode could also be used
> as GPIO or other funcions if guys never need L1ss to be supported.
>
You don't need to configure pinmux in the driver manually. If the platform
desginer knows that CLKREQ# is not used in the endpoint, then the corresponding
pinmux state can be set to non-CLKREQ# function in DT.
I was assuming that CLKREQ# assert/deassert is handled by the endpoint
controller hw without endpoint software intervention.
- Mani
--
மணிவண்ணன் சதாசிவம்
More information about the Linux-rockchip
mailing list