[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