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

Commit 5d047100 authored by Deepak Katragadda's avatar Deepak Katragadda
Browse files

clk: msm: clock-local2: Enable sources before force turning on RCG



Make sure that the RCG parents are turned on before force enabling
it and changing it's configuration.

CRs-Fixed: 1020896
Change-Id: Ia633c4dcbab62fc6a4407c5896e36a7bbef48579
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
parent 0c3a23a4
Loading
Loading
Loading
Loading
+91 −4
Original line number Original line Diff line number Diff line
@@ -275,6 +275,77 @@ static void rcg_clk_disable(struct clk *c)
	rcg_clear_force_enable(rcg);
	rcg_clear_force_enable(rcg);
}
}


static int prepare_enable_rcg_srcs(struct clk *c, struct clk *curr,
					struct clk *new, unsigned long *flags)
{
	int rc;

	rc = clk_prepare(curr);
	if (rc)
		return rc;

	if (c->prepare_count) {
		rc = clk_prepare(new);
		if (rc)
			goto err_new_src_prepare;
	}

	rc = clk_prepare(new);
	if (rc)
		goto err_new_src_prepare2;

	spin_lock_irqsave(&c->lock, *flags);
	rc = clk_enable(curr);
	if (rc) {
		spin_unlock_irqrestore(&c->lock, *flags);
		goto err_curr_src_enable;
	}

	if (c->count) {
		rc = clk_enable(new);
		if (rc) {
			spin_unlock_irqrestore(&c->lock, *flags);
			goto err_new_src_enable;
		}
	}

	rc = clk_enable(new);
	if (rc) {
		spin_unlock_irqrestore(&c->lock, *flags);
		goto err_new_src_enable2;
	}
	return 0;

err_new_src_enable2:
	if (c->count)
		clk_disable(new);
err_new_src_enable:
	clk_disable(curr);
err_curr_src_enable:
	clk_unprepare(new);
err_new_src_prepare2:
	if (c->prepare_count)
		clk_unprepare(new);
err_new_src_prepare:
	clk_unprepare(curr);
	return rc;
}

static void disable_unprepare_rcg_srcs(struct clk *c, struct clk *curr,
					struct clk *new, unsigned long *flags)
{
	clk_disable(new);
	clk_disable(curr);
	if (c->count)
		clk_disable(curr);
	spin_unlock_irqrestore(&c->lock, *flags);

	clk_unprepare(new);
	clk_unprepare(curr);
	if (c->prepare_count)
		clk_unprepare(curr);
}

static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
{
{
	struct clk_freq_tbl *cf, *nf;
	struct clk_freq_tbl *cf, *nf;
@@ -296,7 +367,17 @@ static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
			return rc;
			return rc;
	}
	}


	if (rcg->non_local_control_timeout) {
		/*
		 * __clk_pre_reparent only enables the RCG source if the SW
		 * count for the RCG is non-zero. We need to make sure that
		 * both PLL sources are ON before force turning on the RCG.
		 */
		rc = prepare_enable_rcg_srcs(c, cf->src_clk, nf->src_clk,
								&flags);
	} else
		rc = __clk_pre_reparent(c, nf->src_clk, &flags);
		rc = __clk_pre_reparent(c, nf->src_clk, &flags);

	if (rc)
	if (rc)
		return rc;
		return rc;


@@ -306,8 +387,10 @@ static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
	if ((rcg->non_local_children && c->count) ||
	if ((rcg->non_local_children && c->count) ||
			rcg->non_local_control_timeout) {
			rcg->non_local_control_timeout) {
		/*
		/*
		 * Force enable the RCG here since the clock could be disabled
		 * Force enable the RCG before updating the RCG configuration
		 * between pre_reparent and set_rate.
		 * since the downstream clock/s can be disabled at around the
		 * same time causing the feedback from the CBCR to turn off
		 * the RCG.
		 */
		 */
		rcg_set_force_enable(rcg);
		rcg_set_force_enable(rcg);
		rcg->set_rate(rcg, nf);
		rcg->set_rate(rcg, nf);
@@ -324,6 +407,10 @@ static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
	rcg->current_freq = nf;
	rcg->current_freq = nf;
	c->parent = nf->src_clk;
	c->parent = nf->src_clk;


	if (rcg->non_local_control_timeout)
		disable_unprepare_rcg_srcs(c, cf->src_clk, nf->src_clk,
								&flags);
	else
		__clk_post_reparent(c, cf->src_clk, &flags);
		__clk_post_reparent(c, cf->src_clk, &flags);


	return 0;
	return 0;