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

Commit 655b24bd authored by Deepak Katragadda's avatar Deepak Katragadda Committed by Gerrit - the friendly Code Review server
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 f104c78f
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,10 @@ Optional properties:
			to enable.
			to enable.
 - qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
 - qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
			 enabling the GX GDSC.
			 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
 - resets: reset specifier pair consisting of phandle for the reset controller
			and reset lines used by this controller. These can be
			and reset lines used by this controller. These can be
			supplied only if we support qcom,skip-logic-collapse.
			supplied only if we support qcom,skip-logic-collapse.
+49 −9
Original line number Original line Diff line number Diff line
@@ -28,6 +28,8 @@
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon.h>
#include <linux/clk/qcom.h>
#include <linux/clk/qcom.h>


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

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


	mutex_lock(&gdsc_seq_lock);
	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)
	if (sc->root_en || sc->force_root_en)
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);


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


	if (sc->toggle_logic) {
	if (sc->toggle_logic) {
@@ -258,9 +270,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",
					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,
						sc->rdesc.name, sc->gds_timeout,
						regval, hw_ctrl_regval);
						regval, hw_ctrl_regval);

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

				goto end;
				mutex_unlock(&gdsc_seq_lock);

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


	sc->is_gdsc_enabled = true;
	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);
	mutex_unlock(&gdsc_seq_lock);


@@ -322,6 +332,15 @@ static int gdsc_disable(struct regulator_dev *rdev)


	mutex_lock(&gdsc_seq_lock);
	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)
	if (sc->force_root_en)
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);
		clk_prepare_enable(sc->clocks[sc->root_clk_idx]);


@@ -379,6 +398,9 @@ static int gdsc_disable(struct regulator_dev *rdev)
	if ((sc->is_gdsc_enabled && sc->root_en) || sc->force_root_en)
	if ((sc->is_gdsc_enabled && sc->root_en) || sc->force_root_en)
		clk_disable_unprepare(sc->clocks[sc->root_clk_idx]);
		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;
	sc->is_gdsc_enabled = false;


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


	mutex_lock(&gdsc_seq_lock);
	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);
	regmap_read(sc->regmap, REG_OFFSET, &regval);


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


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

	mutex_unlock(&gdsc_seq_lock);
	mutex_unlock(&gdsc_seq_lock);


	return ret;
	return ret;
@@ -568,6 +602,9 @@ static int gdsc_probe(struct platform_device *pdev)
	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
						"qcom,force-enable-root-clk");
						"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++) {
	for (i = 0; i < sc->clock_count; i++) {
		const char *clock_name;
		const char *clock_name;


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


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

	return 0;
	return 0;
}
}