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

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
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -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"

+54 −61
Original line number Diff line number Diff line
@@ -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,6 +663,11 @@ 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);

	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);
@@ -680,6 +689,7 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
		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);

	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 },
	{ }
};