PCI: qcom: Power on PHY before IPQ8074 DBI register accesses
authorRobert Marko <robimarko@gmail.com>
Thu, 23 Jun 2022 15:50:03 +0000 (17:50 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 13 Jul 2022 19:54:08 +0000 (14:54 -0500)
Currently the Gen2 port in IPQ8074 will cause the system to hang as it
accesses DBI registers in qcom_pcie_init_2_3_3(), and those are only
accesible after phy_power_on().

Move the DBI read/writes to a new qcom_pcie_post_init_2_3_3(), which is
executed after phy_power_on().

Link: https://lore.kernel.org/r/20220623155004.688090-1-robimarko@gmail.com
Fixes: a0fd361db8e5 ("PCI: dwc: Move "dbi", "dbi2", and "addr_space" resource setup into common code")
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Cc: stable@vger.kernel.org # v5.11+
drivers/pci/controller/dwc/pcie-qcom.c

index da13a66..7c08770 100644 (file)
@@ -1036,9 +1036,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
        struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
-       u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
        int i, ret;
-       u32 val;
 
        for (i = 0; i < ARRAY_SIZE(res->rst); i++) {
                ret = reset_control_assert(res->rst[i]);
@@ -1095,6 +1093,33 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
                goto err_clk_aux;
        }
 
+       return 0;
+
+err_clk_aux:
+       clk_disable_unprepare(res->ahb_clk);
+err_clk_ahb:
+       clk_disable_unprepare(res->axi_s_clk);
+err_clk_axi_s:
+       clk_disable_unprepare(res->axi_m_clk);
+err_clk_axi_m:
+       clk_disable_unprepare(res->iface);
+err_clk_iface:
+       /*
+        * Not checking for failure, will anyway return
+        * the original failure in 'ret'.
+        */
+       for (i = 0; i < ARRAY_SIZE(res->rst); i++)
+               reset_control_assert(res->rst[i]);
+
+       return ret;
+}
+
+static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
+{
+       struct dw_pcie *pci = pcie->pci;
+       u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+       u32 val;
+
        writel(SLV_ADDR_SPACE_SZ,
                pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE);
 
@@ -1122,24 +1147,6 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
                PCI_EXP_DEVCTL2);
 
        return 0;
-
-err_clk_aux:
-       clk_disable_unprepare(res->ahb_clk);
-err_clk_ahb:
-       clk_disable_unprepare(res->axi_s_clk);
-err_clk_axi_s:
-       clk_disable_unprepare(res->axi_m_clk);
-err_clk_axi_m:
-       clk_disable_unprepare(res->iface);
-err_clk_iface:
-       /*
-        * Not checking for failure, will anyway return
-        * the original failure in 'ret'.
-        */
-       for (i = 0; i < ARRAY_SIZE(res->rst); i++)
-               reset_control_assert(res->rst[i]);
-
-       return ret;
 }
 
 static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
@@ -1465,6 +1472,7 @@ static const struct qcom_pcie_ops ops_2_4_0 = {
 static const struct qcom_pcie_ops ops_2_3_3 = {
        .get_resources = qcom_pcie_get_resources_2_3_3,
        .init = qcom_pcie_init_2_3_3,
+       .post_init = qcom_pcie_post_init_2_3_3,
        .deinit = qcom_pcie_deinit_2_3_3,
        .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
 };