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: Amit Kucheria <amit.kucheria@canonical.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Родитель
c45dd81400
Коммит
9b839ec0a8
|
@ -52,13 +52,14 @@ static void __clk_disable(struct clk *clk)
|
|||
{
|
||||
if (clk == NULL || IS_ERR(clk))
|
||||
return;
|
||||
|
||||
__clk_disable(clk->parent);
|
||||
__clk_disable(clk->secondary);
|
||||
|
||||
WARN_ON(!clk->usecount);
|
||||
if (!(--clk->usecount) && clk->disable)
|
||||
clk->disable(clk);
|
||||
|
||||
if (!(--clk->usecount)) {
|
||||
if (clk->disable)
|
||||
clk->disable(clk);
|
||||
__clk_disable(clk->parent);
|
||||
__clk_disable(clk->secondary);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
__clk_enable(clk->parent);
|
||||
__clk_enable(clk->secondary);
|
||||
|
||||
if (clk->usecount++ == 0 && clk->enable)
|
||||
clk->enable(clk);
|
||||
if (clk->usecount++ == 0) {
|
||||
__clk_enable(clk->parent);
|
||||
__clk_enable(clk->secondary);
|
||||
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче