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
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
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)
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+
313342static void qcom_pcie_clear_aspm_l0s (struct dw_pcie * pci )
314343{
315344 struct qcom_pcie * pcie = to_qcom_pcie (pci );
@@ -1036,9 +1065,19 @@ static void qcom_pcie_host_post_init_2_7_0(struct qcom_pcie *pcie)
10361065static void qcom_pcie_deinit_2_7_0 (struct qcom_pcie * pcie )
10371066{
10381067 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 );
10391075
10401076 clk_bulk_disable_unprepare (res -> num_clks , res -> clks );
10411077
1078+ reset_control_assert (res -> rst );
1079+ usleep_range (2000 , 2500 );
1080+
10421081 regulator_bulk_disable (ARRAY_SIZE (res -> supplies ), res -> supplies );
10431082}
10441083
@@ -1734,6 +1773,9 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17341773 pcie -> parf + PARF_INT_ALL_MASK );
17351774 }
17361775
1776+ /* If the soc features RPMh, cmd_db must have been prepared by now */
1777+ pcie -> soc_is_rpmh = !cmd_db_ready ();
1778+
17371779 qcom_pcie_icc_opp_update (pcie );
17381780
17391781 if (pcie -> mhi )
@@ -1752,86 +1794,123 @@ static int qcom_pcie_probe(struct platform_device *pdev)
17521794 return ret ;
17531795}
17541796
1755- static int qcom_pcie_suspend_noirq (struct device * dev )
1797+ static int qcom_pcie_resume_noirq (struct device * dev )
17561798{
17571799 struct qcom_pcie * pcie = dev_get_drvdata (dev );
1758- int ret = 0 ;
1800+ int ret ;
17591801
1760- /*
1761- * Set minimum bandwidth required to keep data path functional during
1762- * suspend.
1763- */
1764- if (pcie -> icc_mem ) {
1765- 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 );
17661812 if (ret ) {
1767- dev_err (dev ,
1768- "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n" ,
1769- ret );
1813+ dev_err (pcie -> pci -> dev , "failed to icc_enable: %d" , ret );
17701814 return ret ;
17711815 }
17721816 }
17731817
1774- /*
1775- * Turn OFF the resources only for controllers without active PCIe
1776- * devices. For controllers with active devices, the resources are kept
1777- * ON and the link is expected to be in L0/L1 (sub)states.
1778- *
1779- * Turning OFF the resources for controllers with active PCIe devices
1780- * will trigger access violation during the end of the suspend cycle,
1781- * as kernel tries to access the PCIe devices config space for masking
1782- * MSIs.
1783- *
1784- * Also, it is not desirable to put the link into L2/L3 state as that
1785- * implies VDD supply will be removed and the devices may go into
1786- * powerdown state. This will affect the lifetime of the storage devices
1787- * like NVMe.
1788- */
1789- if (!dw_pcie_link_up (pcie -> pci )) {
1790- qcom_pcie_host_deinit (& pcie -> pci -> pp );
1791- 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 ;
17921826 }
17931827
1794- /*
1795- * Only disable CPU-PCIe interconnect path if the suspend is non-S2RAM.
1796- * Because on some platforms, DBI access can happen very late during the
1797- * S2RAM and a non-active CPU-PCIe interconnect path may lead to NoC
1798- * error.
1799- */
1800- if (pm_suspend_target_state != PM_SUSPEND_MEM ) {
1801- ret = icc_disable (pcie -> icc_cpu );
1802- if (ret )
1803- 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 );
1840+
1841+ qcom_pcie_icc_opp_update (pcie );
1842+
1843+ pcie -> suspended = false;
1844+
1845+ return 0 ;
18041846
1805- if (pcie -> use_pm_opp )
1806- dev_pm_opp_set_opp (pcie -> pci -> dev , NULL );
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 );
18071855 }
1856+
18081857 return ret ;
18091858}
18101859
1811- static int qcom_pcie_resume_noirq (struct device * dev )
1860+ static int qcom_pcie_suspend_noirq (struct device * dev )
18121861{
18131862 struct qcom_pcie * pcie = dev_get_drvdata (dev );
1814- 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 );
1875+
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 );
1886+ if (ret ) {
1887+ dev_err (pcie -> pci -> dev , "failed to icc_enable %d\n" , ret );
18151888
1816- if (pm_suspend_target_state != PM_SUSPEND_MEM ) {
1817- ret = icc_enable (pcie -> icc_cpu );
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 ));
18181898 if (ret ) {
1819- dev_err (dev , "Failed to enable CPU-PCIe interconnect path : %d\n" , ret );
1899+ dev_err (dev , "Failed to set interconnect bandwidth : %d\n" , ret );
18201900 return ret ;
18211901 }
18221902 }
18231903
1824- if (pcie -> suspended ) {
1825- ret = qcom_pcie_host_init (& pcie -> pci -> pp );
1826- if (ret )
1827- return ret ;
1904+ pcie -> suspended = true;
18281905
1829- pcie -> suspended = false;
1830- }
1906+ ret = icc_disable (pcie -> icc_cpu );
1907+ if (ret )
1908+ dev_err (dev , "Failed to disable CPU-PCIe interconnect path: %d\n" , ret );
18311909
1832- qcom_pcie_icc_opp_update (pcie );
1910+ if (pcie -> use_pm_opp )
1911+ dev_pm_opp_set_opp (pcie -> pci -> dev , NULL );
18331912
1834- return 0 ;
1913+ return ret ;
18351914}
18361915
18371916static const struct of_device_id qcom_pcie_match [] = {
0 commit comments