Skip to content

Commit 6b2f39d

Browse files
author
Ziyue Zhang
committed
FROMLIST: PCI: qcom: Add D3cold support
Add support for transitioning PCIe endpoints under host bridge into D3cold by integrating with the DWC core suspend/resume helpers. Implement PME_TurnOff message generation via ELBI_SYS_CTRL and hook it into the DWC host operations so the controller follows the standard PME_TurnOff-based power-down sequence before entering D3cold. When the device is suspended into D3cold, fully tear down interconnect bandwidth, OPP votes. If D3cold is not entered, retain existing behavior by keeping the required interconnect and OPP votes. Use dw_pcie::skip_pwrctrl_off to avoid powering off devices during suspend to preseve wakeup capability of the devices and also not to power on the devices in the init path. Drop the qcom_pcie::suspended flag and rely on the existing dw_pcie::suspended state, which now drives both the power-management flow and the interconnect/OPP handling Link: https://lore.kernel.org/all/20260407-d3cold-v4-5-bb171f75b465@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> Signed-off-by: Ziyue Zhang <ziyue.zhang@oss.qualcomm.com>
1 parent cdf31ed commit 6b2f39d

4 files changed

Lines changed: 37 additions & 15 deletions

File tree

drivers/pci/controller/dwc/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ config PCIE_QCOM
299299
select CRC8
300300
select PCIE_QCOM_COMMON
301301
select PCI_HOST_COMMON
302-
select PCI_PWRCTRL_SLOT
302+
select PCI_PWRCTRL_GENERIC
303303
help
304304
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
305305
PCIe controller uses the DesignWare core plus Qualcomm-specific

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,8 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
11671167
if (!pci_host_common_can_enter_d3cold(pci->pp.bridge))
11681168
return 0;
11691169

1170+
pci->pp.skip_pwrctrl_off = true;
1171+
11701172
if (pci->pp.ops->pme_turn_off) {
11711173
pci->pp.ops->pme_turn_off(&pci->pp);
11721174
} else {
@@ -1222,6 +1224,7 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
12221224
return 0;
12231225

12241226
pci->suspended = false;
1227+
pci->pp.skip_pwrctrl_off = false;
12251228

12261229
if (pci->pp.ops->init) {
12271230
ret = pci->pp.ops->init(&pci->pp);

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ struct dw_pcie_rp {
436436
bool ecam_enabled;
437437
bool native_ecam;
438438
bool skip_l23_ready;
439+
bool skip_pwrctrl_off;
439440
};
440441

441442
struct dw_pcie_ep_ops {

drivers/pci/controller/dwc/pcie-qcom.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,13 +1308,17 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
13081308
if (ret)
13091309
goto err_deinit;
13101310

1311-
ret = pci_pwrctrl_create_devices(pci->dev);
1312-
if (ret)
1313-
goto err_disable_phy;
1311+
if (!pci->suspended) {
1312+
ret = pci_pwrctrl_create_devices(pci->dev);
1313+
if (ret)
1314+
goto err_disable_phy;
1315+
}
13141316

1315-
ret = pci_pwrctrl_power_on_devices(pci->dev);
1316-
if (ret)
1317-
goto err_pwrctrl_destroy;
1317+
if (!pp->skip_pwrctrl_off) {
1318+
ret = pci_pwrctrl_power_on_devices(pci->dev);
1319+
if (ret)
1320+
goto err_pwrctrl_destroy;
1321+
}
13181322

13191323
if (pcie->cfg->ops->post_init) {
13201324
ret = pcie->cfg->ops->post_init(pcie);
@@ -1356,11 +1360,14 @@ static void qcom_pcie_host_deinit(struct dw_pcie_rp *pp)
13561360

13571361
qcom_pcie_perst_assert(pcie);
13581362

1359-
/*
1360-
* No need to destroy pwrctrl devices as this function only gets called
1361-
* during system suspend as of now.
1362-
*/
1363-
pci_pwrctrl_power_off_devices(pci->dev);
1363+
if (!pci->pp.skip_pwrctrl_off) {
1364+
/*
1365+
* No need to destroy pwrctrl devices as this function only gets called
1366+
* during system suspend as of now.
1367+
*/
1368+
pci_pwrctrl_power_off_devices(pci->dev);
1369+
}
1370+
13641371
qcom_pcie_phy_power_off(pcie);
13651372
pcie->cfg->ops->deinit(pcie);
13661373
}
@@ -2051,11 +2058,16 @@ static int qcom_pcie_resume_noirq(struct device *dev)
20512058
ret = icc_enable(pcie->icc_mem);
20522059
if (ret) {
20532060
dev_err(dev, "Failed to enable PCIe-MEM interconnect path: %d\n", ret);
2054-
return ret;
2061+
goto disable_icc_cpu;
20552062
}
2063+
2064+
/*
2065+
* Ignore -ENODEV & -EIO here since it is expected when no endpoint is
2066+
* connected to the PCIe link.
2067+
*/
20562068
ret = dw_pcie_resume_noirq(pcie->pci);
2057-
if (ret && (ret != -ETIMEDOUT))
2058-
return ret;
2069+
if (ret && ret != -ENODEV && ret != -EIO)
2070+
goto disable_icc_mem;
20592071
} else {
20602072
if (pm_suspend_target_state != PM_SUSPEND_MEM) {
20612073
ret = icc_enable(pcie->icc_cpu);
@@ -2070,6 +2082,12 @@ static int qcom_pcie_resume_noirq(struct device *dev)
20702082
qcom_pcie_icc_opp_update(pcie);
20712083

20722084
return 0;
2085+
disable_icc_mem:
2086+
icc_disable(pcie->icc_mem);
2087+
disable_icc_cpu:
2088+
icc_disable(pcie->icc_cpu);
2089+
2090+
return ret;
20732091
}
20742092

20752093
static const struct of_device_id qcom_pcie_match[] = {

0 commit comments

Comments
 (0)