Skip to content

Commit

Permalink
clk: at91: keep slow clk enabled to prevent system hang
Browse files Browse the repository at this point in the history
All slow clk users are not properly claiming it (get + prepare + enable)
before using it.
If all users properly claiming this clock release it, the clock is
disabled, but faulty users still depends on it, and the system hangs.

This fix prevents the slow clock from being disabled, and should solve the
hanging issue, but offending drivers should be patched to properly claim
this clock.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Reported-by: Bo Shen <voice.shen@atmel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Michael Turquette <mturquette@linaro.org>
  • Loading branch information
Boris Brezillon authored and Michael Turquette committed Jan 13, 2015
1 parent 98f87a7 commit dca1a4b
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions drivers/clk/at91/clk-slow.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct clk_sam9x5_slow {

#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)

static struct clk *slow_clk;

static int clk_slow_osc_prepare(struct clk_hw *hw)
{
Expand Down Expand Up @@ -357,6 +358,8 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
clk = clk_register(NULL, &slowck->hw);
if (IS_ERR(clk))
kfree(slowck);
else
slow_clk = clk;

return clk;
}
Expand Down Expand Up @@ -433,6 +436,8 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
clk = clk_register(NULL, &slowck->hw);
if (IS_ERR(clk))
kfree(slowck);
else
slow_clk = clk;

return clk;
}
Expand Down Expand Up @@ -465,3 +470,25 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,

of_clk_add_provider(np, of_clk_src_simple_get, clk);
}

/*
* FIXME: All slow clk users are not properly claiming it (get + prepare +
* enable) before using it.
* If all users properly claiming this clock decide that they don't need it
* anymore (or are removed), it is disabled while faulty users are still
* requiring it, and the system hangs.
* Prevent this clock from being disabled until all users are properly
* requesting it.
* Once this is done we should remove this function and the slow_clk variable.
*/
static int __init of_at91_clk_slow_retain(void)
{
if (!slow_clk)
return 0;

__clk_get(slow_clk);
clk_prepare_enable(slow_clk);

return 0;
}
arch_initcall(of_at91_clk_slow_retain);

0 comments on commit dca1a4b

Please sign in to comment.