Commit 757410bd authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'remotes/lorenzo/pci/qcom'

  - Move qcom driver to bulk clock API (Bjorn Andersson)

  - Add Qualcomm QCS404 PCIe controller support (Bjorn Andersson)

  - Ensure Qualcomm PERST is asserted for at least 100ms (Niklas Cassel)

* remotes/lorenzo/pci/qcom:
  PCI: qcom: Ensure that PERST is asserted for at least 100 ms
  PCI: qcom: Add QCS404 PCIe controller support
  dt-bindings: PCI: qcom: Add QCS404 to the binding
  PCI: qcom: Use clk bulk API for 2.4.0 controllers
parents 3d663fc0 64adde31
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
- "qcom,pcie-msm8996" for msm8996 or apq8096 - "qcom,pcie-msm8996" for msm8996 or apq8096
- "qcom,pcie-ipq4019" for ipq4019 - "qcom,pcie-ipq4019" for ipq4019
- "qcom,pcie-ipq8074" for ipq8074 - "qcom,pcie-ipq8074" for ipq8074
- "qcom,pcie-qcs404" for qcs404
- reg: - reg:
Usage: required Usage: required
...@@ -116,6 +117,15 @@ ...@@ -116,6 +117,15 @@
- "ahb" AHB clock - "ahb" AHB clock
- "aux" Auxiliary clock - "aux" Auxiliary clock
- clock-names:
Usage: required for qcs404
Value type: <stringlist>
Definition: Should contain the following entries
- "iface" AHB clock
- "aux" Auxiliary clock
- "master_bus" AXI Master clock
- "slave_bus" AXI Slave clock
- resets: - resets:
Usage: required Usage: required
Value type: <prop-encoded-array> Value type: <prop-encoded-array>
...@@ -167,6 +177,17 @@ ...@@ -167,6 +177,17 @@
- "ahb" AHB Reset - "ahb" AHB Reset
- "axi_m_sticky" AXI Master Sticky reset - "axi_m_sticky" AXI Master Sticky reset
- reset-names:
Usage: required for qcs404
Value type: <stringlist>
Definition: Should contain the following entries
- "axi_m" AXI Master reset
- "axi_s" AXI Slave reset
- "axi_m_sticky" AXI Master Sticky reset
- "pipe_sticky" PIPE sticky reset
- "pwr" PWR reset
- "ahb" AHB reset
- power-domains: - power-domains:
Usage: required for apq8084 and msm8996/apq8096 Usage: required for apq8084 and msm8996/apq8096
Value type: <prop-encoded-array> Value type: <prop-encoded-array>
...@@ -195,12 +216,12 @@ ...@@ -195,12 +216,12 @@
Definition: A phandle to the PCIe endpoint power supply Definition: A phandle to the PCIe endpoint power supply
- phys: - phys:
Usage: required for apq8084 Usage: required for apq8084 and qcs404
Value type: <phandle> Value type: <phandle>
Definition: List of phandle(s) as listed in phy-names property Definition: List of phandle(s) as listed in phy-names property
- phy-names: - phy-names:
Usage: required for apq8084 Usage: required for apq8084 and qcs404
Value type: <stringlist> Value type: <stringlist>
Definition: Should contain "pciephy" Definition: Should contain "pciephy"
......
...@@ -112,10 +112,10 @@ struct qcom_pcie_resources_2_3_2 { ...@@ -112,10 +112,10 @@ struct qcom_pcie_resources_2_3_2 {
struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY]; struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY];
}; };
#define QCOM_PCIE_2_4_0_MAX_CLOCKS 4
struct qcom_pcie_resources_2_4_0 { struct qcom_pcie_resources_2_4_0 {
struct clk *aux_clk; struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS];
struct clk *master_clk; int num_clks;
struct clk *slave_clk;
struct reset_control *axi_m_reset; struct reset_control *axi_m_reset;
struct reset_control *axi_s_reset; struct reset_control *axi_s_reset;
struct reset_control *pipe_reset; struct reset_control *pipe_reset;
...@@ -178,6 +178,8 @@ static void qcom_ep_reset_assert(struct qcom_pcie *pcie) ...@@ -178,6 +178,8 @@ static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
{ {
/* Ensure that PERST has been asserted for at least 100 ms */
msleep(100);
gpiod_set_value_cansleep(pcie->reset, 0); gpiod_set_value_cansleep(pcie->reset, 0);
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
} }
...@@ -638,18 +640,20 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) ...@@ -638,18 +640,20 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0; struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
struct dw_pcie *pci = pcie->pci; struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev; struct device *dev = pci->dev;
bool is_ipq = of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019");
int ret;
res->aux_clk = devm_clk_get(dev, "aux"); res->clks[0].id = "aux";
if (IS_ERR(res->aux_clk)) res->clks[1].id = "master_bus";
return PTR_ERR(res->aux_clk); res->clks[2].id = "slave_bus";
res->clks[3].id = "iface";
res->master_clk = devm_clk_get(dev, "master_bus"); /* qcom,pcie-ipq4019 is defined without "iface" */
if (IS_ERR(res->master_clk)) res->num_clks = is_ipq ? 3 : 4;
return PTR_ERR(res->master_clk);
res->slave_clk = devm_clk_get(dev, "slave_bus"); ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
if (IS_ERR(res->slave_clk)) if (ret < 0)
return PTR_ERR(res->slave_clk); return ret;
res->axi_m_reset = devm_reset_control_get_exclusive(dev, "axi_m"); res->axi_m_reset = devm_reset_control_get_exclusive(dev, "axi_m");
if (IS_ERR(res->axi_m_reset)) if (IS_ERR(res->axi_m_reset))
...@@ -659,27 +663,33 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) ...@@ -659,27 +663,33 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
if (IS_ERR(res->axi_s_reset)) if (IS_ERR(res->axi_s_reset))
return PTR_ERR(res->axi_s_reset); return PTR_ERR(res->axi_s_reset);
res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe"); if (is_ipq) {
if (IS_ERR(res->pipe_reset)) /*
return PTR_ERR(res->pipe_reset); * These resources relates to the PHY or are secure clocks, but
* are controlled here for IPQ4019
res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev, */
"axi_m_vmid"); res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe");
if (IS_ERR(res->axi_m_vmid_reset)) if (IS_ERR(res->pipe_reset))
return PTR_ERR(res->axi_m_vmid_reset); return PTR_ERR(res->pipe_reset);
res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev, res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev,
"axi_s_xpu"); "axi_m_vmid");
if (IS_ERR(res->axi_s_xpu_reset)) if (IS_ERR(res->axi_m_vmid_reset))
return PTR_ERR(res->axi_s_xpu_reset); return PTR_ERR(res->axi_m_vmid_reset);
res->parf_reset = devm_reset_control_get_exclusive(dev, "parf"); res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev,
if (IS_ERR(res->parf_reset)) "axi_s_xpu");
return PTR_ERR(res->parf_reset); if (IS_ERR(res->axi_s_xpu_reset))
return PTR_ERR(res->axi_s_xpu_reset);
res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
if (IS_ERR(res->phy_reset)) res->parf_reset = devm_reset_control_get_exclusive(dev, "parf");
return PTR_ERR(res->phy_reset); if (IS_ERR(res->parf_reset))
return PTR_ERR(res->parf_reset);
res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
if (IS_ERR(res->phy_reset))
return PTR_ERR(res->phy_reset);
}
res->axi_m_sticky_reset = devm_reset_control_get_exclusive(dev, res->axi_m_sticky_reset = devm_reset_control_get_exclusive(dev,
"axi_m_sticky"); "axi_m_sticky");
...@@ -699,9 +709,11 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) ...@@ -699,9 +709,11 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
if (IS_ERR(res->ahb_reset)) if (IS_ERR(res->ahb_reset))
return PTR_ERR(res->ahb_reset); return PTR_ERR(res->ahb_reset);
res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb"); if (is_ipq) {
if (IS_ERR(res->phy_ahb_reset)) res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb");
return PTR_ERR(res->phy_ahb_reset); if (IS_ERR(res->phy_ahb_reset))
return PTR_ERR(res->phy_ahb_reset);
}
return 0; return 0;
} }
...@@ -719,9 +731,7 @@ static void qcom_pcie_deinit_2_4_0(struct qcom_pcie *pcie) ...@@ -719,9 +731,7 @@ static void qcom_pcie_deinit_2_4_0(struct qcom_pcie *pcie)
reset_control_assert(res->axi_m_sticky_reset); reset_control_assert(res->axi_m_sticky_reset);
reset_control_assert(res->pwr_reset); reset_control_assert(res->pwr_reset);
reset_control_assert(res->ahb_reset); reset_control_assert(res->ahb_reset);
clk_disable_unprepare(res->aux_clk); clk_bulk_disable_unprepare(res->num_clks, res->clks);
clk_disable_unprepare(res->master_clk);
clk_disable_unprepare(res->slave_clk);
} }
static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
...@@ -850,23 +860,9 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) ...@@ -850,23 +860,9 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
usleep_range(10000, 12000); usleep_range(10000, 12000);
ret = clk_prepare_enable(res->aux_clk); ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
if (ret) { if (ret)
dev_err(dev, "cannot prepare/enable iface clock\n"); goto err_clks;
goto err_clk_aux;
}
ret = clk_prepare_enable(res->master_clk);
if (ret) {
dev_err(dev, "cannot prepare/enable core clock\n");
goto err_clk_axi_m;
}
ret = clk_prepare_enable(res->slave_clk);
if (ret) {
dev_err(dev, "cannot prepare/enable phy clock\n");
goto err_clk_axi_s;
}
/* enable PCIe clocks and resets */ /* enable PCIe clocks and resets */
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
...@@ -891,11 +887,7 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) ...@@ -891,11 +887,7 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
return 0; return 0;
err_clk_axi_s: err_clks:
clk_disable_unprepare(res->master_clk);
err_clk_axi_m:
clk_disable_unprepare(res->aux_clk);
err_clk_aux:
reset_control_assert(res->ahb_reset); reset_control_assert(res->ahb_reset);
err_rst_ahb: err_rst_ahb:
reset_control_assert(res->pwr_reset); reset_control_assert(res->pwr_reset);
...@@ -1289,6 +1281,7 @@ static const struct of_device_id qcom_pcie_match[] = { ...@@ -1289,6 +1281,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-msm8996", .data = &ops_2_3_2 }, { .compatible = "qcom,pcie-msm8996", .data = &ops_2_3_2 },
{ .compatible = "qcom,pcie-ipq8074", .data = &ops_2_3_3 }, { .compatible = "qcom,pcie-ipq8074", .data = &ops_2_3_3 },
{ .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 }, { .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 },
{ .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 },
{ } { }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment