PCI: qcom: Power on PHY before DBI register accesses
authorRobert Marko <robimarko@gmail.com>
Thu, 23 Jun 2022 15:50:04 +0000 (17:50 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 13 Jul 2022 19:54:40 +0000 (14:54 -0500)
IPQ8074 requires the PHY to be powered on before accessing DBI registers.
It's not clear whether other variants have the same dependency, but there
seems to be no reason for them to be different, so move all the DBI
accesses from .init() to .post_init() so they are all after phy_power_on().

[bhelgaas: commit log]
Link: https://lore.kernel.org/r/20220623155004.688090-2-robimarko@gmail.com
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/controller/dwc/pcie-qcom.c

index 7c08770..fd2e9b1 100644 (file)
@@ -325,8 +325,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
        struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
-       struct device_node *node = dev->of_node;
-       u32 val;
        int ret;
 
        /* reset the PCIe interface as uboot can leave it undefined state */
@@ -379,6 +377,33 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
                goto err_deassert_axi;
        }
 
+       return 0;
+
+err_deassert_axi:
+       reset_control_assert(res->por_reset);
+err_deassert_por:
+       reset_control_assert(res->pci_reset);
+err_deassert_pci:
+       reset_control_assert(res->phy_reset);
+err_deassert_phy:
+       reset_control_assert(res->ext_reset);
+err_deassert_ext:
+       reset_control_assert(res->ahb_reset);
+err_deassert_ahb:
+       regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
+
+       return ret;
+}
+
+static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie)
+{
+       struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
+       struct dw_pcie *pci = pcie->pci;
+       struct device *dev = pci->dev;
+       struct device_node *node = dev->of_node;
+       u32 val;
+       int ret;
+
        /* enable PCIe clocks and resets */
        val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
        val &= ~BIT(0);
@@ -386,7 +411,7 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
 
        ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
        if (ret)
-               goto err_clks;
+               return ret;
 
        if (of_device_is_compatible(node, "qcom,pcie-ipq8064") ||
            of_device_is_compatible(node, "qcom,pcie-ipq8064-v2")) {
@@ -426,23 +451,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
               pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
 
        return 0;
-
-err_clks:
-       reset_control_assert(res->axi_reset);
-err_deassert_axi:
-       reset_control_assert(res->por_reset);
-err_deassert_por:
-       reset_control_assert(res->pci_reset);
-err_deassert_pci:
-       reset_control_assert(res->phy_reset);
-err_deassert_phy:
-       reset_control_assert(res->ext_reset);
-err_deassert_ext:
-       reset_control_assert(res->ahb_reset);
-err_deassert_ahb:
-       regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
-
-       return ret;
 }
 
 static int qcom_pcie_get_resources_1_0_0(struct qcom_pcie *pcie)
@@ -530,16 +538,6 @@ static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie)
                goto err_slave;
        }
 
-       /* change DBI base address */
-       writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
-
-       if (IS_ENABLED(CONFIG_PCI_MSI)) {
-               u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
-
-               val |= BIT(31);
-               writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
-       }
-
        return 0;
 err_slave:
        clk_disable_unprepare(res->slave_bus);
@@ -555,6 +553,21 @@ err_res:
        return ret;
 }
 
+static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
+{
+       /* change DBI base address */
+       writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
+
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
+
+               val |= BIT(31);
+               writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
+       }
+
+       return 0;
+}
+
 static void qcom_pcie_2_3_2_ltssm_enable(struct qcom_pcie *pcie)
 {
        u32 val;
@@ -623,7 +636,6 @@ static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie)
        struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
-       u32 val;
        int ret;
 
        ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
@@ -656,27 +668,6 @@ static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie)
                goto err_slave_clk;
        }
 
-       /* enable PCIe clocks and resets */
-       val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
-       val &= ~BIT(0);
-       writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
-
-       /* change DBI base address */
-       writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
-
-       /* MAC PHY_POWERDOWN MUX DISABLE  */
-       val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
-       val &= ~BIT(29);
-       writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
-
-       val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
-       val |= BIT(4);
-       writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
-
-       val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
-       val |= BIT(31);
-       writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
-
        return 0;
 
 err_slave_clk:
@@ -697,8 +688,30 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
        struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
+       u32 val;
        int ret;
 
+       /* enable PCIe clocks and resets */
+       val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
+       val &= ~BIT(0);
+       writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
+
+       /* change DBI base address */
+       writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
+
+       /* MAC PHY_POWERDOWN MUX DISABLE  */
+       val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
+       val &= ~BIT(29);
+       writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
+
+       val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+       val |= BIT(4);
+       writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+
+       val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+       val |= BIT(31);
+       writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+
        ret = clk_prepare_enable(res->pipe_clk);
        if (ret) {
                dev_err(dev, "cannot prepare/enable pipe clock\n");
@@ -812,7 +825,6 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
        struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
-       u32 val;
        int ret;
 
        ret = reset_control_assert(res->axi_m_reset);
@@ -937,6 +949,33 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
        if (ret)
                goto err_clks;
 
+       return 0;
+
+err_clks:
+       reset_control_assert(res->ahb_reset);
+err_rst_ahb:
+       reset_control_assert(res->pwr_reset);
+err_rst_pwr:
+       reset_control_assert(res->axi_s_reset);
+err_rst_axi_s:
+       reset_control_assert(res->axi_m_sticky_reset);
+err_rst_axi_m_sticky:
+       reset_control_assert(res->axi_m_reset);
+err_rst_axi_m:
+       reset_control_assert(res->pipe_sticky_reset);
+err_rst_pipe_sticky:
+       reset_control_assert(res->pipe_reset);
+err_rst_pipe:
+       reset_control_assert(res->phy_reset);
+err_rst_phy:
+       reset_control_assert(res->phy_ahb_reset);
+       return ret;
+}
+
+static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie)
+{
+       u32 val;
+
        /* enable PCIe clocks and resets */
        val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
        val &= ~BIT(0);
@@ -959,26 +998,6 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
        writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
 
        return 0;
-
-err_clks:
-       reset_control_assert(res->ahb_reset);
-err_rst_ahb:
-       reset_control_assert(res->pwr_reset);
-err_rst_pwr:
-       reset_control_assert(res->axi_s_reset);
-err_rst_axi_s:
-       reset_control_assert(res->axi_m_sticky_reset);
-err_rst_axi_m_sticky:
-       reset_control_assert(res->axi_m_reset);
-err_rst_axi_m:
-       reset_control_assert(res->pipe_sticky_reset);
-err_rst_pipe_sticky:
-       reset_control_assert(res->pipe_reset);
-err_rst_pipe:
-       reset_control_assert(res->phy_reset);
-err_rst_phy:
-       reset_control_assert(res->phy_ahb_reset);
-       return ret;
 }
 
 static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie)
@@ -1438,6 +1457,7 @@ static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
 static const struct qcom_pcie_ops ops_2_1_0 = {
        .get_resources = qcom_pcie_get_resources_2_1_0,
        .init = qcom_pcie_init_2_1_0,
+       .post_init = qcom_pcie_post_init_2_1_0,
        .deinit = qcom_pcie_deinit_2_1_0,
        .ltssm_enable = qcom_pcie_2_1_0_ltssm_enable,
 };
@@ -1446,6 +1466,7 @@ static const struct qcom_pcie_ops ops_2_1_0 = {
 static const struct qcom_pcie_ops ops_1_0_0 = {
        .get_resources = qcom_pcie_get_resources_1_0_0,
        .init = qcom_pcie_init_1_0_0,
+       .post_init = qcom_pcie_post_init_1_0_0,
        .deinit = qcom_pcie_deinit_1_0_0,
        .ltssm_enable = qcom_pcie_2_1_0_ltssm_enable,
 };
@@ -1464,6 +1485,7 @@ static const struct qcom_pcie_ops ops_2_3_2 = {
 static const struct qcom_pcie_ops ops_2_4_0 = {
        .get_resources = qcom_pcie_get_resources_2_4_0,
        .init = qcom_pcie_init_2_4_0,
+       .post_init = qcom_pcie_post_init_2_4_0,
        .deinit = qcom_pcie_deinit_2_4_0,
        .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
 };