Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30339917 authored by Prakash Gupta's avatar Prakash Gupta Committed by Sudarshan Rajagopalan
Browse files

iommu/arm-smmu: Add support for regulator deferred disable



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.
Add support for regulator deferred disable. The time delay for deferred
disable can be set using dt property qcom,deferred-regulator-disable-delay
in ms.

Change-Id: I462e1999bd81f6332169b24749632d7b247c75c5
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
Signed-off-by: default avatarSudarshan Rajagopalan <sudaraja@codeaurora.org>
parent f7939ea3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
+37 −1
Original line number Diff line number Diff line
@@ -408,6 +408,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 {
@@ -819,6 +820,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)
{
@@ -914,7 +944,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);
@@ -3683,6 +3713,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)