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

Commit 910b070a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu/arm-smmu: Add support for regulator deferred disable" into msm-next

parents cecb6044 30339917
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
@@ -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 {
@@ -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)
{
@@ -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);
@@ -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)