Skip to content

Commit 22e1421

Browse files
committed
Merge remote-tracking branch tech/bus/pci/all into qcom-next
2 parents e94d8b4 + 1103f9c commit 22e1421

File tree

2 files changed

+143
-65
lines changed

2 files changed

+143
-65
lines changed

drivers/pci/controller/dwc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ config PCIE_QCOM_COMMON
292292
config PCIE_QCOM
293293
bool "Qualcomm PCIe controller (host mode)"
294294
depends on OF && (ARCH_QCOM || COMPILE_TEST)
295+
depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n
295296
depends on PCI_MSI
296297
select PCIE_DW_HOST
297298
select CRC8

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

Lines changed: 142 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,19 @@
3232
#include <linux/slab.h>
3333
#include <linux/types.h>
3434
#include <linux/units.h>
35+
#include <soc/qcom/cmd-db.h>
3536

3637
#include "../../pci.h"
3738
#include "pcie-designware.h"
3839
#include "pcie-qcom-common.h"
3940

41+
#include <dt-bindings/interconnect/qcom,icc.h>
42+
#include <dt-bindings/interconnect/qcom,rpm-icc.h>
43+
4044
/* PARF registers */
4145
#define PARF_SYS_CTRL 0x00
4246
#define PARF_PM_CTRL 0x20
47+
#define PARF_PM_STTS 0x24
4348
#define PARF_PCS_DEEMPH 0x34
4449
#define PARF_PCS_SWING 0x38
4550
#define PARF_PHY_CTRL 0x40
@@ -70,6 +75,7 @@
7075

7176
/* ELBI registers */
7277
#define ELBI_SYS_CTRL 0x04
78+
#define ELBI_SYS_CTRL_PME_TURNOFF_MSG BIT(4)
7379

7480
/* DBI registers */
7581
#define AXI_MSTR_RESP_COMP_CTRL0 0x818
@@ -94,7 +100,10 @@
94100
#define L1_CLK_RMV_DIS BIT(1)
95101

96102
/* PARF_PM_CTRL register fields */
97-
#define REQ_NOT_ENTR_L1 BIT(5)
103+
#define REQ_NOT_ENTR_L1 BIT(5) /* "Prevent L0->L1" */
104+
105+
/* PARF_PM_STTS register fields */
106+
#define PM_ENTER_L23 BIT(5)
98107

99108
/* PARF_PCS_DEEMPH register fields */
100109
#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) FIELD_PREP(GENMASK(21, 16), x)
@@ -147,6 +156,7 @@
147156

148157
/* ELBI_SYS_CTRL register fields */
149158
#define ELBI_SYS_CTRL_LT_ENABLE BIT(0)
159+
#define ELBI_SYS_CTRL_PME_TURNOFF_MSG BIT(4)
150160

151161
/* AXI_MSTR_RESP_COMP_CTRL0 register fields */
152162
#define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K 0x4
@@ -276,6 +286,7 @@ struct qcom_pcie {
276286
struct dentry *debugfs;
277287
bool suspended;
278288
bool use_pm_opp;
289+
bool soc_is_rpmh;
279290
};
280291

281292
#define to_qcom_pcie(x) dev_get_drvdata((x)->dev)
@@ -310,6 +321,24 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
310321
return 0;
311322
}
312323

324+
static int qcom_pcie_stop_link(struct dw_pcie *pci)
325+
{
326+
struct qcom_pcie *pcie = to_qcom_pcie(pci);
327+
u32 ret_l23, val;
328+
329+
writel(ELBI_SYS_CTRL_PME_TURNOFF_MSG, pcie->elbi + ELBI_SYS_CTRL);
330+
readl(pcie->elbi + ELBI_SYS_CTRL);
331+
332+
ret_l23 = readl_poll_timeout(pcie->parf + PARF_PM_STTS, val,
333+
val & PM_ENTER_L23, 10000, 100000);
334+
if (ret_l23) {
335+
dev_err(pci->dev, "Failed to enter L2/L3\n");
336+
return -ETIMEDOUT;
337+
}
338+
339+
return 0;
340+
}
341+
313342
static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
314343
{
315344
struct qcom_pcie *pcie = to_qcom_pcie(pci);
@@ -944,27 +973,27 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
944973
return ret;
945974
}
946975

947-
ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
948-
if (ret < 0)
949-
goto err_disable_regulators;
950-
976+
/* Assert the reset to hold the RC in a known state */
951977
ret = reset_control_assert(res->rst);
952978
if (ret) {
953979
dev_err(dev, "reset assert failed (%d)\n", ret);
954-
goto err_disable_clocks;
980+
goto err_disable_regulators;
955981
}
956-
957982
usleep_range(1000, 1500);
958983

984+
/* GCC_PCIE_n_AUX_CLK won't come up if the reset is asserted */
959985
ret = reset_control_deassert(res->rst);
960986
if (ret) {
961987
dev_err(dev, "reset deassert failed (%d)\n", ret);
962-
goto err_disable_clocks;
988+
goto err_disable_regulators;
963989
}
964-
965990
/* Wait for reset to complete, required on SM8450 */
966991
usleep_range(1000, 1500);
967992

993+
ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
994+
if (ret < 0)
995+
goto err_disable_regulators;
996+
968997
/* configure PCIe to RC mode */
969998
writel(DEVICE_TYPE_RC, pcie->parf + PARF_DEVICE_TYPE);
970999

@@ -994,8 +1023,6 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
9941023
writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
9951024

9961025
return 0;
997-
err_disable_clocks:
998-
clk_bulk_disable_unprepare(res->num_clks, res->clks);
9991026
err_disable_regulators:
10001027
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
10011028

@@ -1038,9 +1065,19 @@ static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie)
10381065
static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
10391066
{
10401067
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
1068+
u32 val;
1069+
1070+
/* Disable PCIe clocks and resets */
1071+
val = readl(pcie->parf + PARF_PHY_CTRL);
1072+
val |= PHY_TEST_PWR_DOWN;
1073+
writel(val, pcie->parf + PARF_PHY_CTRL);
1074+
readl(pcie->parf + PARF_PHY_CTRL);
10411075

10421076
clk_bulk_disable_unprepare(res->num_clks, res->clks);
10431077

1078+
reset_control_assert(res->rst);
1079+
usleep_range(2000, 2500);
1080+
10441081
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
10451082
}
10461083

@@ -1736,6 +1773,9 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17361773
pcie->parf + PARF_INT_ALL_MASK);
17371774
}
17381775

1776+
/* If the soc features RPMh, cmd_db must have been prepared by now */
1777+
pcie->soc_is_rpmh = !cmd_db_ready();
1778+
17391779
qcom_pcie_icc_opp_update(pcie);
17401780

17411781
if (pcie->mhi)
@@ -1754,86 +1794,123 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17541794
return ret;
17551795
}
17561796

1757-
static int qcom_pcie_suspend_noirq(struct device *dev)
1797+
static int qcom_pcie_resume_noirq(struct device *dev)
17581798
{
17591799
struct qcom_pcie *pcie = dev_get_drvdata(dev);
1760-
int ret = 0;
1800+
int ret;
17611801

1762-
/*
1763-
* Set minimum bandwidth required to keep data path functional during
1764-
* suspend.
1765-
*/
1766-
if (pcie->icc_mem) {
1767-
ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1));
1802+
if (pcie->soc_is_rpmh) {
1803+
/*
1804+
* Undo the tag change from qcom_pcie_suspend_noirq first in
1805+
* case RPMh spontaneously decides to power collapse the
1806+
* platform based on other inputs.
1807+
*/
1808+
icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_ALWAYS);
1809+
1810+
/* Flush the tag change */
1811+
ret = icc_enable(pcie->icc_mem);
17681812
if (ret) {
1769-
dev_err(dev,
1770-
"Failed to set bandwidth for PCIe-MEM interconnect path: %d\n",
1771-
ret);
1813+
dev_err(pcie->pci->dev, "failed to icc_enable: %d", ret);
17721814
return ret;
17731815
}
17741816
}
17751817

1776-
/*
1777-
* Turn OFF the resources only for controllers without active PCIe
1778-
* devices. For controllers with active devices, the resources are kept
1779-
* ON and the link is expected to be in L0/L1 (sub)states.
1780-
*
1781-
* Turning OFF the resources for controllers with active PCIe devices
1782-
* will trigger access violation during the end of the suspend cycle,
1783-
* as kernel tries to access the PCIe devices config space for masking
1784-
* MSIs.
1785-
*
1786-
* Also, it is not desirable to put the link into L2/L3 state as that
1787-
* implies VDD supply will be removed and the devices may go into
1788-
* powerdown state. This will affect the lifetime of the storage devices
1789-
* like NVMe.
1790-
*/
1791-
if (!dw_pcie_link_up(pcie->pci)) {
1792-
qcom_pcie_host_deinit(&pcie->pci->pp);
1793-
pcie->suspended = true;
1818+
/* Only check this now to make sure the icc tag has been set. */
1819+
if (!pcie->suspended)
1820+
return 0;
1821+
1822+
ret = icc_enable(pcie->icc_cpu);
1823+
if (ret) {
1824+
dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret);
1825+
goto revert_icc_tag;
17941826
}
17951827

1796-
/*
1797-
* Only disable CPU-PCIe interconnect path if the suspend is non-S2RAM.
1798-
* Because on some platforms, DBI access can happen very late during the
1799-
* S2RAM and a non-active CPU-PCIe interconnect path may lead to NoC
1800-
* error.
1801-
*/
1802-
if (pm_suspend_target_state != PM_SUSPEND_MEM) {
1803-
ret = icc_disable(pcie->icc_cpu);
1804-
if (ret)
1805-
dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret);
1828+
ret = qcom_pcie_host_init(&pcie->pci->pp);
1829+
if (ret)
1830+
goto revert_icc_tag;
1831+
1832+
dw_pcie_setup_rc(&pcie->pci->pp);
1833+
1834+
ret = qcom_pcie_start_link(pcie->pci);
1835+
if (ret)
1836+
goto deinit_host;
1837+
1838+
/* Ignore the retval, the devices may come up later. */
1839+
dw_pcie_wait_for_link(pcie->pci);
18061840

1807-
if (pcie->use_pm_opp)
1808-
dev_pm_opp_set_opp(pcie->pci->dev, NULL);
1841+
qcom_pcie_icc_opp_update(pcie);
1842+
1843+
pcie->suspended = false;
1844+
1845+
return 0;
1846+
1847+
deinit_host:
1848+
qcom_pcie_host_deinit(&pcie->pci->pp);
1849+
revert_icc_tag:
1850+
if (pcie->soc_is_rpmh) {
1851+
icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_WAKE);
1852+
1853+
/* Ignore the retval, failing here would be tragic anyway.. */
1854+
icc_enable(pcie->icc_mem);
18091855
}
1856+
18101857
return ret;
18111858
}
18121859

1813-
static int qcom_pcie_resume_noirq(struct device *dev)
1860+
static int qcom_pcie_suspend_noirq(struct device *dev)
18141861
{
18151862
struct qcom_pcie *pcie = dev_get_drvdata(dev);
1816-
int ret;
1863+
int ret = 0;
1864+
1865+
if (pcie->suspended)
1866+
return 0;
1867+
1868+
if (dw_pcie_link_up(pcie->pci)) {
1869+
ret = qcom_pcie_stop_link(pcie->pci);
1870+
if (ret)
1871+
return ret;
1872+
}
1873+
1874+
qcom_pcie_host_deinit(&pcie->pci->pp);
18171875

1818-
if (pm_suspend_target_state != PM_SUSPEND_MEM) {
1819-
ret = icc_enable(pcie->icc_cpu);
1876+
if (pcie->soc_is_rpmh) {
1877+
/*
1878+
* The PCIe RC may be covertly accessed by the secure firmware
1879+
* on sleep exit. Use the WAKE bucket to let RPMh pull the plug
1880+
* on PCIe in sleep, but guarantee it comes back up for resume.
1881+
*/
1882+
icc_set_tag(pcie->icc_mem, QCOM_ICC_TAG_WAKE);
1883+
1884+
/* Flush the tag change */
1885+
ret = icc_enable(pcie->icc_mem);
18201886
if (ret) {
1821-
dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret);
1887+
dev_err(pcie->pci->dev, "failed to icc_enable %d\n", ret);
1888+
1889+
/* Revert everything and pray icc calls succeed */
1890+
return qcom_pcie_resume_noirq(dev);
1891+
}
1892+
} else {
1893+
/*
1894+
* Set minimum bandwidth required to keep data path functional
1895+
* during suspend.
1896+
*/
1897+
ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1));
1898+
if (ret) {
1899+
dev_err(dev, "Failed to set interconnect bandwidth: %d\n", ret);
18221900
return ret;
18231901
}
18241902
}
18251903

1826-
if (pcie->suspended) {
1827-
ret = qcom_pcie_host_init(&pcie->pci->pp);
1828-
if (ret)
1829-
return ret;
1904+
pcie->suspended = true;
18301905

1831-
pcie->suspended = false;
1832-
}
1906+
ret = icc_disable(pcie->icc_cpu);
1907+
if (ret)
1908+
dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret);
18331909

1834-
qcom_pcie_icc_opp_update(pcie);
1910+
if (pcie->use_pm_opp)
1911+
dev_pm_opp_set_opp(pcie->pci->dev, NULL);
18351912

1836-
return 0;
1913+
return ret;
18371914
}
18381915

18391916
static const struct of_device_id qcom_pcie_match[] = {

0 commit comments

Comments
 (0)