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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:24:22 +0000 (14:24 +0200)
[ Upstream commit a0e43bb9973b06ce5c666f0901e104e2037c1b34 ]

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+
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/pci/controller/dwc/pcie-qcom.c

index 45210c6380b1fc9835526c5d7eacb134c1830b83..4c599699e3c8871e6580d69d1ad326e14475e53d 100644 (file)
@@ -1024,9 +1024,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]);
@@ -1083,6 +1081,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);
 
@@ -1110,24 +1135,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)
@@ -1423,6 +1430,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,
 };