clk: at91: keep slow clk enabled to prevent system hang

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>

authored by Boris Brezillon and committed by Michael Turquette dca1a4b5 98f87a7b

+27
+27
drivers/clk/at91/clk-slow.c
··· 70 70 71 71 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) 72 72 73 + static struct clk *slow_clk; 73 74 74 75 static int clk_slow_osc_prepare(struct clk_hw *hw) 75 76 { ··· 358 357 clk = clk_register(NULL, &slowck->hw); 359 358 if (IS_ERR(clk)) 360 359 kfree(slowck); 360 + else 361 + slow_clk = clk; 361 362 362 363 return clk; 363 364 } ··· 436 433 clk = clk_register(NULL, &slowck->hw); 437 434 if (IS_ERR(clk)) 438 435 kfree(slowck); 436 + else 437 + slow_clk = clk; 439 438 440 439 return clk; 441 440 } ··· 470 465 471 466 of_clk_add_provider(np, of_clk_src_simple_get, clk); 472 467 } 468 + 469 + /* 470 + * FIXME: All slow clk users are not properly claiming it (get + prepare + 471 + * enable) before using it. 472 + * If all users properly claiming this clock decide that they don't need it 473 + * anymore (or are removed), it is disabled while faulty users are still 474 + * requiring it, and the system hangs. 475 + * Prevent this clock from being disabled until all users are properly 476 + * requesting it. 477 + * Once this is done we should remove this function and the slow_clk variable. 478 + */ 479 + static int __init of_at91_clk_slow_retain(void) 480 + { 481 + if (!slow_clk) 482 + return 0; 483 + 484 + __clk_get(slow_clk); 485 + clk_prepare_enable(slow_clk); 486 + 487 + return 0; 488 + } 489 + arch_initcall(of_at91_clk_slow_retain);