[PATCH v3 1/2] PCI: dw-rockchip: Configure L1sub support
Shawn Lin
shawn.lin at rock-chips.com
Thu Oct 23 20:19:45 PDT 2025
在 2025/10/24 星期五 11:09, Frank Li 写道:
> On Fri, Oct 24, 2025 at 08:43:28AM +0800, Shawn Lin wrote:
>> 在 2025/10/23 星期四 23:46, Frank Li 写道:
>>> On Thu, Oct 23, 2025 at 10:51:22AM +0800, Shawn Lin wrote:
>>>> 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 at rock-chips.com>
>>>>
>>>> ---
>>>>
>>>> Changes in v3:
>>>> - rephrease the changelog
>>>> - use FIELD_PREP_WM16
>>>> - rename to rockchip_pcie_configure_l1sub
>>>> - disable L1ss for EP mode
>>>>
>>>> Changes in v2:
>>>> - drop of_pci_clkreq_presnt API
>>>> - drop dependency of Niklas's patch
>>>>
>>>> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 43 +++++++++++++++++++++++++++
>>>> 1 file changed, 43 insertions(+)
>>>>
>>>> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
>>>> index 3e2752c..25d2474 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,37 @@ 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);
>>>> + u32 cap, l1subcap;
>>>> +
>>>> + /* 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);
>>>> + return;
>>>> + }
>>>> +
>>>> + /* Otherwise, pull down CLKREQ# and disable L1 PM substates */
>>>> + rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
>>>> + PCIE_CLIENT_POWER_CON);
>>>
>>> Looks like you force pull down clkreq should be enough, needn't disable
>>> L1SS. when RC force clkreq is low, Ref CLK always on even if L1SS enabled.
>>>
>>> Of course it depend on hardware implementation, But I think FULL_DOWN have
>>> high priority to force clkreq to low then PCI_L1SS control.
>>>
>>
>> Hi Frank,
>>
>> Thanks for your review. TBH, the basic idea here I think is not to
>> advertise a capability if the HW as whole hasn't been well prepared to
>> support it yet. So I'd prefer to keep it as-is.
>>
>
> If that, I prefer do it at dwc common driver or provide helper function to
> avoid other vendor to copy same logic.
Right, definitely we could improve it once another driver need it. :)
>
> Frank
>
>>> Frank
>>>
>>>> + 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 +302,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 +340,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 +452,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.7.4
>>>>
>>>>
>>>> _______________________________________________
>>>> Linux-rockchip mailing list
>>>> Linux-rockchip at lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>>>
>>
>>
>> _______________________________________________
>> Linux-rockchip mailing list
>> Linux-rockchip at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
More information about the Linux-rockchip
mailing list