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

Commit 9b839ec0 authored by Amit Kucheria's avatar Amit Kucheria Committed by Sascha Hauer
Browse files

arm: mxc: utilise usecount field in clock operations

This patch fixes the clock refcounting when reparenting is used.

Boot-tested on imx51 babbage board.

Sascha pointed out a good explanation of refcounting here:
http://www.spinics.net/lists/arm-kernel/msg85879.html



Signed-off-by: default avatarAmit Kucheria <amit.kucheria@canonical.com>
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
parent c45dd814
Loading
Loading
Loading
Loading
+25 −12
Original line number Diff line number Diff line
@@ -52,13 +52,14 @@ static void __clk_disable(struct clk *clk)
{
	if (clk == NULL || IS_ERR(clk))
		return;
	WARN_ON(!clk->usecount);

	if (!(--clk->usecount)) {
		if (clk->disable)
			clk->disable(clk);
		__clk_disable(clk->parent);
		__clk_disable(clk->secondary);

	WARN_ON(!clk->usecount);
	if (!(--clk->usecount) && clk->disable)
		clk->disable(clk);
	}
}

static int __clk_enable(struct clk *clk)
@@ -66,12 +67,13 @@ static int __clk_enable(struct clk *clk)
	if (clk == NULL || IS_ERR(clk))
		return -EINVAL;

	if (clk->usecount++ == 0) {
		__clk_enable(clk->parent);
		__clk_enable(clk->secondary);

	if (clk->usecount++ == 0 && clk->enable)
		if (clk->enable)
			clk->enable(clk);

	}
	return 0;
}

@@ -160,17 +162,28 @@ EXPORT_SYMBOL(clk_set_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
	int ret = -EINVAL;
	struct clk *old;

	if (clk == NULL || IS_ERR(clk) || parent == NULL ||
	    IS_ERR(parent) || clk->set_parent == NULL)
		return ret;

	if (clk->usecount)
		clk_enable(parent);

	mutex_lock(&clocks_mutex);
	ret = clk->set_parent(clk, parent);
	if (ret == 0)
	if (ret == 0) {
		old = clk->parent;
		clk->parent = parent;
	} else {
		old = parent;
	}
	mutex_unlock(&clocks_mutex);

	if (clk->usecount)
		clk_disable(old);

	return ret;
}
EXPORT_SYMBOL(clk_set_parent);