Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d7a8c8a authored by Laura Abbott's avatar Laura Abbott
Browse files

msm: iommu: Add support for alternate iface clocks



In addition to alternate core clocks, some IOMMU require additional
votes for extra iface clocks. Add support to the IOMMU driver to support
these clocks.

Change-Id: I45ddaec970e3beb527c2cfb522a18ccaaea9fe77
Signed-off-by: default avatarLaura Abbott <lauraa@codeaurora.org>
parent 2782cfa4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ Optional properties:
Optional properties:
- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
  access to the IOMMU configuration registers
- qcom,needs-alt-iface-clk : boolean to enable the secondary iface clock for
  access to the IOMMU configuration registers
- qcom,iommu-bfb-regs : An array of unsigned 32-bit integers corresponding to
  BFB register addresses that need to be configured for performance tuning
  purposes. If this property is present, the qcom,iommu-bfb-data must also be
+3 −1
Original line number Diff line number Diff line
@@ -90,7 +90,8 @@ struct msm_iommu_bfb_settings {
 * @irq:	Interrupt number
 * @clk:	The bus clock for this IOMMU hardware instance
 * @pclk:	The clock for the IOMMU bus interconnect
 * @aclk:	Alternate clock for this IOMMU core, if any
 * @aclk:	Alternate core clock for this IOMMU core, if any
 * @aiclk:	Alternate interface clock for this IOMMU core, if any
 * @name:	Human-readable name of this IOMMU device
 * @gdsc:	Regulator needed to power this HW block (v2 only)
 * @bfb_settings: Optional BFB performance tuning parameters
@@ -113,6 +114,7 @@ struct msm_iommu_drvdata {
	struct clk *clk;
	struct clk *pclk;
	struct clk *aclk;
	struct clk *aiclk;
	const char *name;
	struct regulator *gdsc;
	struct regulator *alt_gdsc;
+20 −5
Original line number Diff line number Diff line
@@ -97,14 +97,18 @@ static int __enable_clocks(struct msm_iommu_drvdata *drvdata)

	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		clk_disable_unprepare(drvdata->pclk);
		goto fail1;

	if (drvdata->aclk) {
		ret = clk_prepare_enable(drvdata->aclk);
		if (ret) {
			clk_disable_unprepare(drvdata->clk);
			clk_disable_unprepare(drvdata->pclk);
		if (ret)
			goto fail2;
	}

	if (drvdata->aiclk) {
		ret = clk_prepare_enable(drvdata->aiclk);
		if (ret)
			goto fail3;
	}

	if (drvdata->clk_reg_virt) {
@@ -116,12 +120,23 @@ static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
		/* Ensure clock is on before continuing */
		mb();
	}
	return 0;

fail3:
	if (drvdata->aclk)
		clk_disable_unprepare(drvdata->aclk);
fail2:
	clk_disable_unprepare(drvdata->clk);
fail1:
	clk_disable_unprepare(drvdata->pclk);
fail:
	return ret;
}

static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
{
	if (drvdata->aiclk)
		clk_disable_unprepare(drvdata->aiclk);
	if (drvdata->aclk)
		clk_disable_unprepare(drvdata->aclk);
	clk_disable_unprepare(drvdata->clk);
+14 −1
Original line number Diff line number Diff line
@@ -281,7 +281,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
	struct iommu_pmon *pmon_info;
	struct msm_iommu_drvdata *drvdata;
	struct resource *r;
	int ret, needs_alt_core_clk;
	int ret, needs_alt_core_clk, needs_alt_iface_clk;
	int global_cfg_irq, global_client_irq;

	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
@@ -328,6 +328,14 @@ static int msm_iommu_probe(struct platform_device *pdev)
			return PTR_ERR(drvdata->aclk);
	}

	needs_alt_iface_clk = of_property_read_bool(pdev->dev.of_node,
						   "qcom,needs-alt-iface-clk");
	if (needs_alt_iface_clk) {
		drvdata->aiclk = devm_clk_get(&pdev->dev, "alt_iface_clk");
		if (IS_ERR(drvdata->aclk))
			return PTR_ERR(drvdata->aiclk);
	}

	if (clk_get_rate(drvdata->clk) == 0) {
		ret = clk_round_rate(drvdata->clk, 1000);
		clk_set_rate(drvdata->clk, ret);
@@ -338,6 +346,11 @@ static int msm_iommu_probe(struct platform_device *pdev)
		clk_set_rate(drvdata->aclk, ret);
	}

	if (drvdata->aiclk && clk_get_rate(drvdata->aiclk) == 0) {
		ret = clk_round_rate(drvdata->aiclk, 1000);
		clk_set_rate(drvdata->aiclk, ret);
	}

	ret = msm_iommu_parse_dt(pdev, drvdata);
	if (ret)
		return ret;