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:
parent
8627019a66
commit
22c9f71a24
4 changed files with 40 additions and 40 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
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,7 +68,8 @@ fail:
|
|||
|
||||
static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
|
||||
{
|
||||
if (drvdata->clk)
|
||||
if (drvdata->aclk)
|
||||
clk_disable_unprepare(drvdata->aclk);
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret) {
|
||||
clk_put(drvdata->clk);
|
||||
goto fail_pclk;
|
||||
if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) {
|
||||
ret = clk_round_rate(drvdata->aclk, 1);
|
||||
clk_set_rate(drvdata->aclk, ret);
|
||||
}
|
||||
} else
|
||||
drvdata->clk = NULL;
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue