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
This commit is contained in:
commit
757410bd97
|
@ -10,6 +10,7 @@
|
|||
- "qcom,pcie-msm8996" for msm8996 or apq8096
|
||||
- "qcom,pcie-ipq4019" for ipq4019
|
||||
- "qcom,pcie-ipq8074" for ipq8074
|
||||
- "qcom,pcie-qcs404" for qcs404
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
|
@ -116,6 +117,15 @@
|
|||
- "ahb" AHB 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:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
|
@ -167,6 +177,17 @@
|
|||
- "ahb" AHB 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:
|
||||
Usage: required for apq8084 and msm8996/apq8096
|
||||
Value type: <prop-encoded-array>
|
||||
|
@ -195,12 +216,12 @@
|
|||
Definition: A phandle to the PCIe endpoint power supply
|
||||
|
||||
- phys:
|
||||
Usage: required for apq8084
|
||||
Usage: required for apq8084 and qcs404
|
||||
Value type: <phandle>
|
||||
Definition: List of phandle(s) as listed in phy-names property
|
||||
|
||||
- phy-names:
|
||||
Usage: required for apq8084
|
||||
Usage: required for apq8084 and qcs404
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain "pciephy"
|
||||
|
||||
|
|
|
@ -112,10 +112,10 @@ struct qcom_pcie_resources_2_3_2 {
|
|||
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 clk *aux_clk;
|
||||
struct clk *master_clk;
|
||||
struct clk *slave_clk;
|
||||
struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS];
|
||||
int num_clks;
|
||||
struct reset_control *axi_m_reset;
|
||||
struct reset_control *axi_s_reset;
|
||||
struct reset_control *pipe_reset;
|
||||
|
@ -178,6 +178,8 @@ static void qcom_ep_reset_assert(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);
|
||||
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)
|
|||
struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
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");
|
||||
if (IS_ERR(res->aux_clk))
|
||||
return PTR_ERR(res->aux_clk);
|
||||
res->clks[0].id = "aux";
|
||||
res->clks[1].id = "master_bus";
|
||||
res->clks[2].id = "slave_bus";
|
||||
res->clks[3].id = "iface";
|
||||
|
||||
res->master_clk = devm_clk_get(dev, "master_bus");
|
||||
if (IS_ERR(res->master_clk))
|
||||
return PTR_ERR(res->master_clk);
|
||||
/* qcom,pcie-ipq4019 is defined without "iface" */
|
||||
res->num_clks = is_ipq ? 3 : 4;
|
||||
|
||||
res->slave_clk = devm_clk_get(dev, "slave_bus");
|
||||
if (IS_ERR(res->slave_clk))
|
||||
return PTR_ERR(res->slave_clk);
|
||||
ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
res->axi_m_reset = devm_reset_control_get_exclusive(dev, "axi_m");
|
||||
if (IS_ERR(res->axi_m_reset))
|
||||
|
@ -659,27 +663,33 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
|
|||
if (IS_ERR(res->axi_s_reset))
|
||||
return PTR_ERR(res->axi_s_reset);
|
||||
|
||||
res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe");
|
||||
if (IS_ERR(res->pipe_reset))
|
||||
return PTR_ERR(res->pipe_reset);
|
||||
if (is_ipq) {
|
||||
/*
|
||||
* These resources relates to the PHY or are secure clocks, but
|
||||
* are controlled here for IPQ4019
|
||||
*/
|
||||
res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe");
|
||||
if (IS_ERR(res->pipe_reset))
|
||||
return PTR_ERR(res->pipe_reset);
|
||||
|
||||
res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev,
|
||||
"axi_m_vmid");
|
||||
if (IS_ERR(res->axi_m_vmid_reset))
|
||||
return PTR_ERR(res->axi_m_vmid_reset);
|
||||
res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev,
|
||||
"axi_m_vmid");
|
||||
if (IS_ERR(res->axi_m_vmid_reset))
|
||||
return PTR_ERR(res->axi_m_vmid_reset);
|
||||
|
||||
res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev,
|
||||
"axi_s_xpu");
|
||||
if (IS_ERR(res->axi_s_xpu_reset))
|
||||
return PTR_ERR(res->axi_s_xpu_reset);
|
||||
res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev,
|
||||
"axi_s_xpu");
|
||||
if (IS_ERR(res->axi_s_xpu_reset))
|
||||
return PTR_ERR(res->axi_s_xpu_reset);
|
||||
|
||||
res->parf_reset = devm_reset_control_get_exclusive(dev, "parf");
|
||||
if (IS_ERR(res->parf_reset))
|
||||
return PTR_ERR(res->parf_reset);
|
||||
res->parf_reset = devm_reset_control_get_exclusive(dev, "parf");
|
||||
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->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,
|
||||
"axi_m_sticky");
|
||||
|
@ -699,9 +709,11 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
|
|||
if (IS_ERR(res->ahb_reset))
|
||||
return PTR_ERR(res->ahb_reset);
|
||||
|
||||
res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb");
|
||||
if (IS_ERR(res->phy_ahb_reset))
|
||||
return PTR_ERR(res->phy_ahb_reset);
|
||||
if (is_ipq) {
|
||||
res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb");
|
||||
if (IS_ERR(res->phy_ahb_reset))
|
||||
return PTR_ERR(res->phy_ahb_reset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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->pwr_reset);
|
||||
reset_control_assert(res->ahb_reset);
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
clk_disable_unprepare(res->slave_clk);
|
||||
clk_bulk_disable_unprepare(res->num_clks, res->clks);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ret = clk_prepare_enable(res->aux_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable iface clock\n");
|
||||
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;
|
||||
}
|
||||
ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
|
||||
if (ret)
|
||||
goto err_clks;
|
||||
|
||||
/* enable PCIe clocks and resets */
|
||||
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
|
||||
|
@ -891,11 +887,7 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
|
|||
|
||||
return 0;
|
||||
|
||||
err_clk_axi_s:
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
err_clk_axi_m:
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
err_clk_aux:
|
||||
err_clks:
|
||||
reset_control_assert(res->ahb_reset);
|
||||
err_rst_ahb:
|
||||
reset_control_assert(res->pwr_reset);
|
||||
|
@ -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-ipq8074", .data = &ops_2_3_3 },
|
||||
{ .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 },
|
||||
{ .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue