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

Commit 726a9505 authored by Vivek Aknurwar's avatar Vivek Aknurwar Committed by Gerrit - the friendly Code Review server
Browse files

clk: qcom: Add support to proxy vote until clk controllers sync states



Clock consumers gets deferred due to their dependencies during device
boot/probes, and can not put essential vdd vote before clock late init
clk_disable_unused() un-votes them. This behavior breaks functionality of
keeping clocks/feature continuously enabled from boot to HLOS. Putting
proxy vdd votes will ensure that votes are hold till consumer sync states
and it gives chance to consumers act on necessary votes when it's ready.

Also clock controller can not rely on consumers to vote vdd votes during
boot/probe sequence in all paths of clk provided consumed APIs. Putting
proxy votes makes sure that clk driver can access it's provided register
access.

Change-Id: I79301ff354b3ab53cc7c05db5e1dc75223228de6
Signed-off-by: default avatarVivek Aknurwar <viveka@codeaurora.org>
parent a0bcc432
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -271,6 +271,10 @@ int qcom_cc_really_probe(struct platform_device *pdev,
	if (ret)
		return ret;

	ret = clk_vdd_proxy_vote(&pdev->dev, desc);
	if (ret)
		return ret;

	if (desc->num_resets) {
		ret = devm_reset_controller_register(dev, &reset->rcdev);
		if (ret)
@@ -362,6 +366,8 @@ void qcom_cc_sync_state(struct device *dev, const struct qcom_cc_desc *desc)
{
	dev_info(dev, "sync-state\n");
	clk_sync_state(dev);

	clk_vdd_proxy_unvote(dev, desc);
}
EXPORT_SYMBOL(qcom_cc_sync_state);

+38 −0
Original line number Diff line number Diff line
@@ -209,3 +209,41 @@ int clk_regulator_init(struct device *dev, const struct qcom_cc_desc *desc)
	return 0;
}

int clk_vdd_proxy_vote(struct device *dev, const struct qcom_cc_desc *desc)
{
	struct clk_vdd_class_data vdd_data;
	struct clk_vdd_class *vdd_class;
	u32 i;
	int ret = 0;

	for (i = 0; i < desc->num_clk_regulators; i++) {
		vdd_data.vdd_class = vdd_class = desc->clk_regulators[i];

		ret = clk_vote_vdd_level(&vdd_data,
					 vdd_class->num_levels - 1);
		if (ret)
			WARN(ret, "%s failed, ret=%d\n", __func__, ret);
	}

	return ret;
}

int clk_vdd_proxy_unvote(struct device *dev, const struct qcom_cc_desc *desc)
{
	struct clk_vdd_class_data vdd_data;
	struct clk_vdd_class *vdd_class;
	u32 i;
	int ret = 0;

	for (i = 0; i < desc->num_clk_regulators; i++) {
		vdd_data.vdd_class = vdd_class = desc->clk_regulators[i];

		ret = clk_unvote_vdd_level(&vdd_data,
					   vdd_class->num_levels - 1);
		if (ret)
			WARN(ret, "clk_unvote_vdd_level failed ret=%d\n", ret);
	}

	return ret;
}
+2 −0
Original line number Diff line number Diff line
@@ -72,4 +72,6 @@ int clk_vote_vdd_level(struct clk_vdd_class_data *vdd_class, int level);
int clk_unvote_vdd_level(struct clk_vdd_class_data *vdd_class, int level);
int clk_list_rate_vdd_level(struct clk_hw *hw, unsigned int rate);
int clk_regulator_init(struct device *dev, const struct qcom_cc_desc *desc);
int clk_vdd_proxy_vote(struct device *dev, const struct qcom_cc_desc *desc);
int clk_vdd_proxy_unvote(struct device *dev, const struct qcom_cc_desc *desc);
#endif