Loading Documentation/devicetree/bindings/iommu/arm,smmu.txt +6 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,12 @@ conditions. retention. No cache invalidation operations involving asid may be used. - qcom,deferred-regulator-disable-delay : The time delay for deferred regulator disable in ms. In case of unmap call, regulator is enabled/disabled. This may introduce additional delay. For clients who do not detach, it's not possible to keep regulator vote while smmu is attached. Type is <u32>. - clocks : List of clocks to be used during SMMU register access. See Documentation/devicetree/bindings/clock/clock-bindings.txt for information about the format. For each clock specified Loading drivers/iommu/arm-smmu.c +37 −1 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct arm_smmu_power_resources { /* Protects clock_refs_count */ spinlock_t clock_refs_lock; int clock_refs_count; int regulator_defer; }; struct arm_smmu_device { Loading Loading @@ -627,6 +628,35 @@ static void arm_smmu_unrequest_bus(struct arm_smmu_power_resources *pwr) WARN_ON(msm_bus_scale_client_update_request(pwr->bus_client, 0)); } static int arm_smmu_disable_regulators(struct arm_smmu_power_resources *pwr) { struct regulator_bulk_data *consumers; int i; int num_consumers, ret, r; num_consumers = pwr->num_gdscs; consumers = pwr->gdscs; for (i = num_consumers - 1; i >= 0; --i) { ret = regulator_disable_deferred(consumers[i].consumer, pwr->regulator_defer); if (ret != 0) goto err; } return 0; err: pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); for (++i; i < num_consumers; ++i) { r = regulator_enable(consumers[i].consumer); if (r != 0) pr_err("Failed to rename %s: %d\n", consumers[i].supply, r); } return ret; } /* Clocks must be prepared before this (arm_smmu_prepare_clocks) */ static int arm_smmu_power_on_atomic(struct arm_smmu_power_resources *pwr) { Loading Loading @@ -722,7 +752,7 @@ static void arm_smmu_power_off_slow(struct arm_smmu_power_resources *pwr) } arm_smmu_unprepare_clocks(pwr); regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs); arm_smmu_disable_regulators(pwr); arm_smmu_unrequest_bus(pwr); pwr->power_count = 0; mutex_unlock(&pwr->power_lock); Loading Loading @@ -3520,6 +3550,12 @@ static int arm_smmu_init_regulators(struct arm_smmu_power_resources *pwr) if (!pwr->gdscs) return -ENOMEM; if (!of_property_read_u32(dev->of_node, "qcom,deferred-regulator-disable-delay", &(pwr->regulator_defer))) dev_info(dev, "regulator defer delay %d\n", pwr->regulator_defer); i = 0; of_property_for_each_string(dev->of_node, "qcom,regulator-names", prop, cname) Loading Loading
Documentation/devicetree/bindings/iommu/arm,smmu.txt +6 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,12 @@ conditions. retention. No cache invalidation operations involving asid may be used. - qcom,deferred-regulator-disable-delay : The time delay for deferred regulator disable in ms. In case of unmap call, regulator is enabled/disabled. This may introduce additional delay. For clients who do not detach, it's not possible to keep regulator vote while smmu is attached. Type is <u32>. - clocks : List of clocks to be used during SMMU register access. See Documentation/devicetree/bindings/clock/clock-bindings.txt for information about the format. For each clock specified Loading
drivers/iommu/arm-smmu.c +37 −1 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct arm_smmu_power_resources { /* Protects clock_refs_count */ spinlock_t clock_refs_lock; int clock_refs_count; int regulator_defer; }; struct arm_smmu_device { Loading Loading @@ -627,6 +628,35 @@ static void arm_smmu_unrequest_bus(struct arm_smmu_power_resources *pwr) WARN_ON(msm_bus_scale_client_update_request(pwr->bus_client, 0)); } static int arm_smmu_disable_regulators(struct arm_smmu_power_resources *pwr) { struct regulator_bulk_data *consumers; int i; int num_consumers, ret, r; num_consumers = pwr->num_gdscs; consumers = pwr->gdscs; for (i = num_consumers - 1; i >= 0; --i) { ret = regulator_disable_deferred(consumers[i].consumer, pwr->regulator_defer); if (ret != 0) goto err; } return 0; err: pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); for (++i; i < num_consumers; ++i) { r = regulator_enable(consumers[i].consumer); if (r != 0) pr_err("Failed to rename %s: %d\n", consumers[i].supply, r); } return ret; } /* Clocks must be prepared before this (arm_smmu_prepare_clocks) */ static int arm_smmu_power_on_atomic(struct arm_smmu_power_resources *pwr) { Loading Loading @@ -722,7 +752,7 @@ static void arm_smmu_power_off_slow(struct arm_smmu_power_resources *pwr) } arm_smmu_unprepare_clocks(pwr); regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs); arm_smmu_disable_regulators(pwr); arm_smmu_unrequest_bus(pwr); pwr->power_count = 0; mutex_unlock(&pwr->power_lock); Loading Loading @@ -3520,6 +3550,12 @@ static int arm_smmu_init_regulators(struct arm_smmu_power_resources *pwr) if (!pwr->gdscs) return -ENOMEM; if (!of_property_read_u32(dev->of_node, "qcom,deferred-regulator-disable-delay", &(pwr->regulator_defer))) dev_info(dev, "regulator defer delay %d\n", pwr->regulator_defer); i = 0; of_property_for_each_string(dev->of_node, "qcom,regulator-names", prop, cname) Loading