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