Skip to content

Commit b5e719f

Browse files
shawn1221bjorn-helgaas
authored andcommitted
PCI: dw-rockchip: Configure L1SS support
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 RK3568 TRM 1.1 Part 2, or section '11.6.6.4 L1 Substate' in the RK3588 TRM 1.0 Part2. [bhelgaas: set pci->l1ss_support so DWC core preserves L1SS Capability bits; drop corresponding code here, include updates from https://lore.kernel.org/r/aRRG8wv13HxOCqgA@ryzen] Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/1761187883-150120-1-git-send-email-shawn.lin@rock-chips.com Link: https://patch.msgid.link/20251118214312.2598220-4-helgaas@kernel.org
1 parent 07c99ea commit b5e719f

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

drivers/pci/controller/dwc/pcie-dw-rockchip.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@
6262
/* Interrupt Mask Register Related to Miscellaneous Operation */
6363
#define PCIE_CLIENT_INTR_MASK_MISC 0x24
6464

65+
/* Power Management Control Register */
66+
#define PCIE_CLIENT_POWER_CON 0x2c
67+
#define PCIE_CLKREQ_READY FIELD_PREP_WM16(BIT(0), 1)
68+
#define PCIE_CLKREQ_NOT_READY FIELD_PREP_WM16(BIT(0), 0)
69+
#define PCIE_CLKREQ_PULL_DOWN FIELD_PREP_WM16(GENMASK(13, 12), 1)
70+
6571
/* Hot Reset Control Register */
6672
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
6773
#define PCIE_LTSSM_APP_DLY2_EN BIT(1)
@@ -85,6 +91,7 @@ struct rockchip_pcie {
8591
struct regulator *vpcie3v3;
8692
struct irq_domain *irq_domain;
8793
const struct rockchip_pcie_of_data *data;
94+
bool supports_clkreq;
8895
};
8996

9097
struct rockchip_pcie_of_data {
@@ -200,6 +207,35 @@ static bool rockchip_pcie_link_up(struct dw_pcie *pci)
200207
return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP;
201208
}
202209

210+
/*
211+
* See e.g. section '11.6.6.4 L1 Substate' in the RK3588 TRM V1.0 for the steps
212+
* needed to support L1 substates. Currently, just enable L1 substates for RC
213+
* mode if CLKREQ# is properly connected and supports-clkreq is present in DT.
214+
* For EP mode, there are more things should be done to actually save power in
215+
* L1 substates, so disable L1 substates until there is proper support.
216+
*/
217+
static void rockchip_pcie_configure_l1ss(struct dw_pcie *pci)
218+
{
219+
struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
220+
221+
/* Enable L1 substates if CLKREQ# is properly connected */
222+
if (rockchip->supports_clkreq) {
223+
rockchip_pcie_writel_apb(rockchip, PCIE_CLKREQ_READY,
224+
PCIE_CLIENT_POWER_CON);
225+
pci->l1ss_support = true;
226+
return;
227+
}
228+
229+
/*
230+
* Otherwise, assert CLKREQ# unconditionally. Since
231+
* pci->l1ss_support is not set, the DWC core will prevent L1
232+
* Substates support from being advertised.
233+
*/
234+
rockchip_pcie_writel_apb(rockchip,
235+
PCIE_CLKREQ_PULL_DOWN | PCIE_CLKREQ_NOT_READY,
236+
PCIE_CLIENT_POWER_CON);
237+
}
238+
203239
static void rockchip_pcie_enable_l0s(struct dw_pcie *pci)
204240
{
205241
u32 cap, lnkcap;
@@ -264,6 +300,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
264300
irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,
265301
rockchip);
266302

303+
rockchip_pcie_configure_l1ss(pci);
267304
rockchip_pcie_enable_l0s(pci);
268305

269306
return 0;
@@ -412,6 +449,9 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
412449
return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst),
413450
"failed to get reset lines\n");
414451

452+
rockchip->supports_clkreq = of_property_read_bool(pdev->dev.of_node,
453+
"supports-clkreq");
454+
415455
return 0;
416456
}
417457

0 commit comments

Comments
 (0)