From: Mitchel Humpherys <mitchelh@xxxxxxxxxxxxxx> This adds the support to turn on the regulators required for SMMUs. It is turned on during the SMMU probe and remains 'on' till the device exists. Signed-off-by: Sricharan R <sricharan@xxxxxxxxxxxxxx> --- .../devicetree/bindings/iommu/arm,smmu.txt | 3 ++ drivers/iommu/arm-smmu.c | 48 +++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index c2cf4fe..433d778 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -60,6 +60,9 @@ conditions. Documentation/devicetree/bindings/clock/clock-bindings.txt for more info. +- vdd-supply : Phandle of the regulator that should be powered on during + SMMU register access. + Example: smmu { diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 80d56f0a..c92de50 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -326,6 +326,8 @@ struct arm_smmu_device { int num_clocks; struct clk **clocks; + + struct regulator *regulator; }; struct arm_smmu_cfg { @@ -559,6 +561,22 @@ static void __arm_smmu_free_bitmap(unsigned long *map, int idx) clear_bit(idx, map); } +static int arm_smmu_enable_regulators(struct arm_smmu_device *smmu) +{ + if (!smmu->regulator) + return 0; + + return regulator_enable(smmu->regulator); +} + +static int arm_smmu_disable_regulators(struct arm_smmu_device *smmu) +{ + if (!smmu->regulator) + return 0; + + return regulator_disable(smmu->regulator); +} + /* Wait for any pending TLB invalidations to complete */ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu) { @@ -1583,6 +1601,20 @@ static int arm_smmu_id_size_to_bits(int size) } } +static int arm_smmu_init_regulators(struct arm_smmu_device *smmu) +{ + struct device *dev = smmu->dev; + + if (!of_get_property(dev->of_node, "vdd-supply", NULL)) + return 0; + + smmu->regulator = devm_regulator_get(dev, "vdd"); + if (IS_ERR(smmu->regulator)) + return PTR_ERR(smmu->regulator); + + return 0; +} + static int arm_smmu_init_clocks(struct arm_smmu_device *smmu) { const char *cname; @@ -1841,11 +1873,21 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = arm_smmu_init_regulators(smmu); + if (err) + goto out_put_masters; + err = arm_smmu_init_clocks(smmu); if (err) goto out_put_masters; - arm_smmu_enable_clocks(smmu); + err = arm_smmu_enable_regulators(smmu); + if (err) + goto out_put_masters; + + err = arm_smmu_enable_clocks(smmu); + if (err) + goto out_disable_regulators; err = arm_smmu_device_cfg_probe(smmu); if (err) @@ -1908,6 +1950,9 @@ out_free_irqs: out_disable_clocks: arm_smmu_disable_clocks(smmu); +out_disable_regulators: + arm_smmu_disable_regulators(smmu); + out_put_masters: for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { struct arm_smmu_master *master @@ -1953,6 +1998,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); arm_smmu_disable_clocks(smmu); + arm_smmu_disable_regulators(smmu); return 0; } -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html