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

Commit 9e7d8b0b authored by Deepak Katragadda's avatar Deepak Katragadda Committed by David Collins
Browse files

clk: qcom: gdsc-regulator: Place a min operational vote on GDSC parent



For GDSCs that reside on domains that are collapsible and
support a minimum voltage of retention, explicitly vote on
the minimal operating voltage, LowSVS for the rail. This is
required as an interim step before enabling/disabling the
GDSC. Once that's done and the GDSC has latched on to its
new state, remove this voltage vote.

Change-Id: Ibac43bba8248d68f8355d1a9db9cfcbfb9fa7557
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
parent 73bab4a1
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -50,6 +50,10 @@ Optional properties:
			to enable.
 - qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
			 enabling the GX GDSC.
 - qcom,vote-parent-supply-voltage: If present, need to vote for a minimum
			operational voltage (LOW_SVS) on the GDSC parent
			regulator prior to configuring it. The vote is removed
			once the GDSC FSM has latched on to the new state.
 - resets: reset specifier pair consisting of phandle for the reset controller
			and reset lines used by this controller. These can be
			supplied only if we support qcom,skip-logic-collapse.
+49 −9
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <linux/mfd/syscon.h>
#include <linux/clk/qcom.h>

#include <dt-bindings/regulator/qcom,rpmh-regulator-levels.h>

/* GDSCR */
#define PWR_ON_MASK		BIT(31)
#define CLK_DIS_WAIT_MASK	(0xF << 12)
@@ -61,6 +63,7 @@ struct gdsc {
	bool			is_gdsc_enabled;
	bool			allow_clear;
	bool			reset_aon;
	bool			vote_supply_voltage;
	int			clock_count;
	int			reset_count;
	int			root_clk_idx;
@@ -159,6 +162,15 @@ static int gdsc_enable(struct regulator_dev *rdev)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
			return ret;
		}
	}

	if (sc->root_en || sc->force_root_en)
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);

@@ -166,8 +178,8 @@ static int gdsc_enable(struct regulator_dev *rdev)
	if (regval & HW_CONTROL_MASK) {
		dev_warn(&rdev->dev, "Invalid enable while %s is under HW control\n",
				sc->rdesc.name);
		mutex_unlock(&gdsc_seq_lock);
		return -EBUSY;
		ret = -EBUSY;
		goto end;
	}

	if (sc->toggle_logic) {
@@ -250,9 +262,7 @@ static int gdsc_enable(struct regulator_dev *rdev)
					dev_err(&rdev->dev, "%s final state (after additional %d us timeout): 0x%x, GDS_HW_CTRL: 0x%x\n",
						sc->rdesc.name, sc->gds_timeout,
						regval, hw_ctrl_regval);

					mutex_unlock(&gdsc_seq_lock);
					return ret;
					goto end;
				}
			} else {
				dev_err(&rdev->dev, "%s enable timed out: 0x%x\n",
@@ -264,10 +274,7 @@ static int gdsc_enable(struct regulator_dev *rdev)
				dev_err(&rdev->dev, "%s final state: 0x%x (%d us after timeout)\n",
					sc->rdesc.name, regval,
					sc->gds_timeout);

				mutex_unlock(&gdsc_seq_lock);

				return ret;
				goto end;
			}
		}
	} else {
@@ -300,6 +307,9 @@ static int gdsc_enable(struct regulator_dev *rdev)
		clk_disable_unprepare(sc->clocks[sc->root_clk_idx]);

	sc->is_gdsc_enabled = true;
end:
	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);

	mutex_unlock(&gdsc_seq_lock);

@@ -314,6 +324,15 @@ static int gdsc_disable(struct regulator_dev *rdev)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
			return ret;
		}
	}

	if (sc->force_root_en)
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);

@@ -371,6 +390,9 @@ static int gdsc_disable(struct regulator_dev *rdev)
	if ((sc->is_gdsc_enabled && sc->root_en) || sc->force_root_en)
		clk_disable_unprepare(sc->clocks[sc->root_clk_idx]);

	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);

	sc->is_gdsc_enabled = false;

	mutex_unlock(&gdsc_seq_lock);
@@ -401,6 +423,15 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)

	mutex_lock(&gdsc_seq_lock);

	if (sc->vote_supply_voltage) {
		ret = regulator_set_voltage(sc->rdev->supply,
				RPMH_REGULATOR_LEVEL_LOW_SVS, INT_MAX);
		if (ret) {
			mutex_unlock(&gdsc_seq_lock);
			return ret;
		}
	}

	regmap_read(sc->regmap, REG_OFFSET, &regval);

	switch (mode) {
@@ -444,6 +475,9 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)
		break;
	}

	if (sc->vote_supply_voltage)
		regulator_set_voltage(sc->rdev->supply, 0, INT_MAX);

	mutex_unlock(&gdsc_seq_lock);

	return ret;
@@ -560,6 +594,9 @@ static int gdsc_probe(struct platform_device *pdev)
	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
						"qcom,force-enable-root-clk");

	sc->vote_supply_voltage = of_property_read_bool(pdev->dev.of_node,
					"qcom,vote-parent-supply-voltage");

	for (i = 0; i < sc->clock_count; i++) {
		const char *clock_name;

@@ -704,6 +741,9 @@ static int gdsc_probe(struct platform_device *pdev)
		return PTR_ERR(sc->rdev);
	}

	if (!sc->rdev->supply)
		sc->vote_supply_voltage = false;

	return 0;
}