Commit 30962d9d authored by Paul Walmsley's avatar Paul Walmsley
Browse files

OMAP2+ clock: revise omap2_clk_{disable,enable}()



Simplify the code in the omap2_clk_disable() and omap2_clk_enable()
functions, reducing levels of indentation.  This makes the code easier
to read.  Add some additional debugging pr_debug()s here also to help
others understand what is going on.

Revise the omap2_clk_disable() logic so that it now attempts to
disable the clock's clockdomain before recursing up the clock tree.
Simultaneously, ensure that omap2_clk_enable() is called on parent
clocks first, before enabling the clockdomain.  This ensures that a
parent clock's clockdomain is enabled before the child clock's
clockdomain.  These sequences should be the inverse of each other.

Revise the omap2_clk_enable() logic so that it now cleans up after
itself upon encountering an error.  Previously, an error enabling a
parent clock could have resulted in inconsistent usecounts on the
enclosing clockdomain.

Remove the trivial _omap2_clk_disable() and _omap2_clk_enable() static
functions, and replace it with the clkops calls that they were
executing.

For all this to work, the clockdomain omap2_clkdm_clk_enable() and
omap2_clkdm_clk_disable() code must not return an error on clockdomains
without CLKSTCTRL registers; so modify those functions to simply return 0
in that case.

While here, add some basic kerneldoc documentation on both functions,
and get rid of some old non-CodingStyle-compliant comments that have
existed since the dawn of time (at least, the OMAP clock framework's
time).

Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
parent 4d30e82c
Loading
Loading
Loading
Loading
+91 −44
Original line number Original line Diff line number Diff line
@@ -37,9 +37,9 @@


u8 cpu_mask;
u8 cpu_mask;


/*-------------------------------------------------------------------------
/*
 * OMAP2/3/4 specific clock functions
 * OMAP2+ specific clock functions
 *-------------------------------------------------------------------------*/
 */


/* Private functions */
/* Private functions */


@@ -71,20 +71,6 @@ static void _omap2_module_wait_ready(struct clk *clk)
			     clk->name);
			     clk->name);
}
}


/* Enables clock without considering parent dependencies or use count
 * REVISIT: Maybe change this to use clk->enable like on omap1?
 */
static int _omap2_clk_enable(struct clk *clk)
{
	return clk->ops->enable(clk);
}

/* Disables clock without considering parent dependencies or use count */
static void _omap2_clk_disable(struct clk *clk)
{
	clk->ops->disable(clk);
}

/* Public functions */
/* Public functions */


/**
/**
@@ -245,46 +231,106 @@ const struct clkops clkops_omap2_dflt = {
	.disable	= omap2_dflt_clk_disable,
	.disable	= omap2_dflt_clk_disable,
};
};


/**
 * omap2_clk_disable - disable a clock, if the system is not using it
 * @clk: struct clk * to disable
 *
 * Decrements the usecount on struct clk @clk.  If there are no users
 * left, call the clkops-specific clock disable function to disable it
 * in hardware.  If the clock is part of a clockdomain (which they all
 * should be), request that the clockdomain be disabled.  (It too has
 * a usecount, and so will not be disabled in the hardware until it no
 * longer has any users.)  If the clock has a parent clock (most of
 * them do), then call ourselves, recursing on the parent clock.  This
 * can cause an entire branch of the clock tree to be powered off by
 * simply disabling one clock.  Intended to be called with the clockfw_lock
 * spinlock held.  No return value.
 */
void omap2_clk_disable(struct clk *clk)
void omap2_clk_disable(struct clk *clk)
{
{
	if (clk->usecount > 0 && !(--clk->usecount)) {
	if (clk->usecount == 0) {
		_omap2_clk_disable(clk);
		WARN(1, "clock: %s: omap2_clk_disable() called, but usecount "
		if (clk->parent)
		     "already 0?", clk->name);
			omap2_clk_disable(clk->parent);
		return;
	}

	pr_debug("clock: %s: decrementing usecount\n", clk->name);

	clk->usecount--;

	if (clk->usecount > 0)
		return;

	pr_debug("clock: %s: disabling in hardware\n", clk->name);

	clk->ops->disable(clk);

	if (clk->clkdm)
	if (clk->clkdm)
		omap2_clkdm_clk_disable(clk->clkdm, clk);
		omap2_clkdm_clk_disable(clk->clkdm, clk);


	}
	if (clk->parent)
		omap2_clk_disable(clk->parent);
}
}


/**
 * omap2_clk_enable - request that the system enable a clock
 * @clk: struct clk * to enable
 *
 * Increments the usecount on struct clk @clk.  If there were no users
 * previously, then recurse up the clock tree, enabling all of the
 * clock's parents and all of the parent clockdomains, and finally,
 * enabling @clk's clockdomain, and @clk itself.  Intended to be
 * called with the clockfw_lock spinlock held.  Returns 0 upon success
 * or a negative error code upon failure.
 */
int omap2_clk_enable(struct clk *clk)
int omap2_clk_enable(struct clk *clk)
{
{
	int ret = 0;
	int ret;


	if (clk->usecount++ == 0) {
	pr_debug("clock: %s: incrementing usecount\n", clk->name);
		if (clk->clkdm)

			omap2_clkdm_clk_enable(clk->clkdm, clk);
	clk->usecount++;

	if (clk->usecount > 1)
		return 0;

	pr_debug("clock: %s: enabling in hardware\n", clk->name);


	if (clk->parent) {
	if (clk->parent) {
		ret = omap2_clk_enable(clk->parent);
		ret = omap2_clk_enable(clk->parent);
			if (ret)
		if (ret) {
				goto err;
			WARN(1, "clock: %s: could not enable parent %s: %d\n",
			     clk->name, clk->parent->name, ret);
			goto oce_err1;
		}
	}
	}


		ret = _omap2_clk_enable(clk);
	if (clk->clkdm) {
		ret = omap2_clkdm_clk_enable(clk->clkdm, clk);
		if (ret) {
		if (ret) {
			if (clk->parent)
			WARN(1, "clock: %s: could not enable clockdomain %s: "
				omap2_clk_disable(clk->parent);
			     "%d\n", clk->name, clk->clkdm->name, ret);

			goto oce_err2;
			goto err;
		}
		}
	}
	}
	return ret;


err:
	ret = clk->ops->enable(clk);
	if (ret) {
		WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret);
		goto oce_err3;
	}

	return 0;

oce_err3:
	if (clk->clkdm)
	if (clk->clkdm)
		omap2_clkdm_clk_disable(clk->clkdm, clk);
		omap2_clkdm_clk_disable(clk->clkdm, clk);
oce_err2:
	if (clk->parent)
		omap2_clk_disable(clk->parent);
oce_err1:
	clk->usecount--;
	clk->usecount--;

	return ret;
	return ret;
}
}


@@ -325,9 +371,9 @@ const struct clkops clkops_omap3_noncore_dpll_ops = {
#endif
#endif




/*-------------------------------------------------------------------------
/*
 * Omap2 clock reset and init functions
 * OMAP2+ clock reset and init functions
 *-------------------------------------------------------------------------*/
 */


#ifdef CONFIG_OMAP_RESET_CLOCKS
#ifdef CONFIG_OMAP_RESET_CLOCKS
void omap2_clk_disable_unused(struct clk *clk)
void omap2_clk_disable_unused(struct clk *clk)
@@ -344,8 +390,9 @@ void omap2_clk_disable_unused(struct clk *clk)
	if (cpu_is_omap34xx()) {
	if (cpu_is_omap34xx()) {
		omap2_clk_enable(clk);
		omap2_clk_enable(clk);
		omap2_clk_disable(clk);
		omap2_clk_disable(clk);
	} else
	} else {
		_omap2_clk_disable(clk);
		clk->ops->disable(clk);
	}
	if (clk->clkdm != NULL)
	if (clk->clkdm != NULL)
		pwrdm_clkdm_state_switch(clk->clkdm);
		pwrdm_clkdm_state_switch(clk->clkdm);
}
}
+8 −2
Original line number Original line Diff line number Diff line
@@ -978,7 +978,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
	 * downstream clocks for debugging purposes?
	 * downstream clocks for debugging purposes?
	 */
	 */


	if (!clkdm || !clk || !clkdm->clkstctrl_reg)
	if (!clkdm || !clk)
		return -EINVAL;
		return -EINVAL;


	if (atomic_inc_return(&clkdm->usecount) > 1)
	if (atomic_inc_return(&clkdm->usecount) > 1)
@@ -989,6 +989,9 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
		 clk->name);
		 clk->name);


	if (!clkdm->clkstctrl_reg)
		return 0;

	v = omap2_clkdm_clktrctrl_read(clkdm);
	v = omap2_clkdm_clktrctrl_read(clkdm);


	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
@@ -1030,7 +1033,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
	 * downstream clocks for debugging purposes?
	 * downstream clocks for debugging purposes?
	 */
	 */


	if (!clkdm || !clk || !clkdm->clkstctrl_reg)
	if (!clkdm || !clk)
		return -EINVAL;
		return -EINVAL;


#ifdef DEBUG
#ifdef DEBUG
@@ -1048,6 +1051,9 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
		 clk->name);
		 clk->name);


	if (!clkdm->clkstctrl_reg)
		return 0;

	v = omap2_clkdm_clktrctrl_read(clkdm);
	v = omap2_clkdm_clktrctrl_read(clkdm);


	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||