1
0
Fork 0
mirror of https://github.com/followmsi/android_kernel_google_msm.git synced 2024-11-06 23:17:41 +00:00

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 <stepanm@codeaurora.org>
This commit is contained in:
Stepan Moskovchenko 2012-07-24 19:24:14 -07:00 committed by Stephen Boyd
parent 8627019a66
commit 22c9f71a24
4 changed files with 40 additions and 40 deletions
Documentation/devicetree/bindings/iommu
arch/arm/mach-msm/include/mach
drivers/iommu

View file

@ -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 {

View file

@ -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;

View file

@ -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);
}

View file

@ -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)