From 22c9f71a2408c205aad32df603c42f138c1f92a1 Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Tue, 24 Jul 2012 19:24:14 -0700 Subject: [PATCH] msm: iommu: Support alternate core clocks Refactor the IOMMU clock control code to always require a core clock as well as an interface clock. Add support for an optional alternate core clock and update device tree bindings accordingly. Clean up the probe function to remove needless enabling / disabling of clocks. Change-Id: I4d744ffabc1e6fb123bacfda324f64408257cb25 Signed-off-by: Stepan Moskovchenko --- .../devicetree/bindings/iommu/msm_iommu.txt | 4 ++ arch/arm/mach-msm/include/mach/iommu.h | 2 + drivers/iommu/msm_iommu-v2.c | 17 ++++-- drivers/iommu/msm_iommu_dev-v2.c | 57 +++++++------------ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt index e9fb1a2399c7..f5a2590e52aa 100644 --- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt +++ b/Documentation/devicetree/bindings/iommu/msm_iommu.txt @@ -16,6 +16,10 @@ Required properties: - qcom,iommu-smt-size : Number of SMR entries in the SMT of this HW block - vdd-supply : vdd-supply: phandle to GDSC regulator controlling this IOMMU. +Optional properties: +- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for + access to the IOMMU configuration registers + Example: qcom,iommu@fda64000 { diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h index 28c53dbc92bf..b14f145ed261 100644 --- a/arch/arm/mach-msm/include/mach/iommu.h +++ b/arch/arm/mach-msm/include/mach/iommu.h @@ -72,6 +72,7 @@ struct msm_iommu_ctx_dev { * @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 * @name: Human-readable name of this IOMMU device * @gdsc: Regulator needed to power this HW block (v2 only) * @nsmr: Size of the SMT on this HW block (v2 only) @@ -85,6 +86,7 @@ struct msm_iommu_drvdata { int ttbr_split; struct clk *clk; struct clk *pclk; + struct clk *aclk; const char *name; struct regulator *gdsc; unsigned int nsmr; diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c index 48edf96ccae3..28ad0ffe2d32 100644 --- a/drivers/iommu/msm_iommu-v2.c +++ b/drivers/iommu/msm_iommu-v2.c @@ -51,10 +51,16 @@ static int __enable_clocks(struct msm_iommu_drvdata *drvdata) if (ret) goto fail; - if (drvdata->clk) { - ret = clk_prepare_enable(drvdata->clk); - if (ret) + ret = clk_prepare_enable(drvdata->clk); + if (ret) + clk_disable_unprepare(drvdata->pclk); + + if (drvdata->aclk) { + ret = clk_prepare_enable(drvdata->aclk); + if (ret) { + clk_disable_unprepare(drvdata->clk); clk_disable_unprepare(drvdata->pclk); + } } fail: return ret; @@ -62,8 +68,9 @@ fail: static void __disable_clocks(struct msm_iommu_drvdata *drvdata) { - if (drvdata->clk) - clk_disable_unprepare(drvdata->clk); + if (drvdata->aclk) + clk_disable_unprepare(drvdata->aclk); + clk_disable_unprepare(drvdata->clk); clk_disable_unprepare(drvdata->pclk); } diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c index 14ed5d9fdf49..8c26f956bb54 100644 --- a/drivers/iommu/msm_iommu_dev-v2.c +++ b/drivers/iommu/msm_iommu_dev-v2.c @@ -69,7 +69,7 @@ static int __devinit msm_iommu_probe(struct platform_device *pdev) { struct msm_iommu_drvdata *drvdata; struct resource *r; - int ret; + int ret, needs_alt_core_clk; if (msm_iommu_root_dev == pdev) return 0; @@ -93,55 +93,42 @@ static int __devinit msm_iommu_probe(struct platform_device *pdev) if (IS_ERR(drvdata->gdsc)) return -EINVAL; - drvdata->pclk = clk_get(&pdev->dev, "iface_clk"); + drvdata->pclk = devm_clk_get(&pdev->dev, "iface_clk"); if (IS_ERR(drvdata->pclk)) return PTR_ERR(drvdata->pclk); - ret = clk_prepare_enable(drvdata->pclk); - if (ret) - goto fail_enable; + drvdata->clk = devm_clk_get(&pdev->dev, "core_clk"); + if (IS_ERR(drvdata->clk)) + return PTR_ERR(drvdata->clk); - drvdata->clk = clk_get(&pdev->dev, "core_clk"); - if (!IS_ERR(drvdata->clk)) { - if (clk_get_rate(drvdata->clk) == 0) { - ret = clk_round_rate(drvdata->clk, 1); - clk_set_rate(drvdata->clk, ret); - } + needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node, + "qcom,needs-alt-core-clk"); + if (needs_alt_core_clk) { + drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk"); + if (IS_ERR(drvdata->aclk)) + return PTR_ERR(drvdata->aclk); + } - ret = clk_prepare_enable(drvdata->clk); - if (ret) { - clk_put(drvdata->clk); - goto fail_pclk; - } - } else - drvdata->clk = NULL; + if (clk_get_rate(drvdata->clk) == 0) { + ret = clk_round_rate(drvdata->clk, 1); + clk_set_rate(drvdata->clk, ret); + } + + if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) { + ret = clk_round_rate(drvdata->aclk, 1); + clk_set_rate(drvdata->aclk, ret); + } ret = msm_iommu_parse_dt(pdev, drvdata); if (ret) - goto fail_clk; + return ret; pr_info("device %s mapped at %p, with %d ctx banks\n", drvdata->name, drvdata->base, drvdata->ncb); platform_set_drvdata(pdev, drvdata); - if (drvdata->clk) - clk_disable_unprepare(drvdata->clk); - - clk_disable_unprepare(drvdata->pclk); - return 0; - -fail_clk: - if (drvdata->clk) { - clk_disable_unprepare(drvdata->clk); - clk_put(drvdata->clk); - } -fail_pclk: - clk_disable_unprepare(drvdata->pclk); -fail_enable: - clk_put(drvdata->pclk); - return ret; } static int __devexit msm_iommu_remove(struct platform_device *pdev)