aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2014-02-24 13:10:13 -0500
committerMike Turquette <mturquette@linaro.org>2014-03-19 20:15:29 -0400
commit1771b10d605d26ccee771a7fb4b08718c124097a (patch)
treed809a7fdba093e327160f745b5cd36c0d1664830 /drivers/clk
parent00fa6e5d138a87f1b1bc8ae634c5f6fe513338c6 (diff)
clk: respect the clock dependencies in of_clk_init
Until now the clock providers were initialized in the order found in the device tree. This led to have the dependencies between the clocks not respected: children clocks could be initialized before their parent clocks. Instead of forcing each platform to manage its own initialization order, this patch adds this work inside the framework itself. Using the data of the device tree the of_clk_init function now delayed the initialization of a clock provider if its parent provider was not ready yet. The strict dependency check (all parents of a given clk must be initialized) was added by Boris BREZILLON Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 895b3d204e22..e1a192240055 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2539,24 +2539,99 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
2539} 2539}
2540EXPORT_SYMBOL_GPL(of_clk_get_parent_name); 2540EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
2541 2541
2542struct clock_provider {
2543 of_clk_init_cb_t clk_init_cb;
2544 struct device_node *np;
2545 struct list_head node;
2546};
2547
2548static LIST_HEAD(clk_provider_list);
2549
2550/*
2551 * This function looks for a parent clock. If there is one, then it
2552 * checks that the provider for this parent clock was initialized, in
2553 * this case the parent clock will be ready.
2554 */
2555static int parent_ready(struct device_node *np)
2556{
2557 int i = 0;
2558
2559 while (true) {
2560 struct clk *clk = of_clk_get(np, i);
2561
2562 /* this parent is ready we can check the next one */
2563 if (!IS_ERR(clk)) {
2564 clk_put(clk);
2565 i++;
2566 continue;
2567 }
2568
2569 /* at least one parent is not ready, we exit now */
2570 if (PTR_ERR(clk) == -EPROBE_DEFER)
2571 return 0;
2572
2573 /*
2574 * Here we make assumption that the device tree is
2575 * written correctly. So an error means that there is
2576 * no more parent. As we didn't exit yet, then the
2577 * previous parent are ready. If there is no clock
2578 * parent, no need to wait for them, then we can
2579 * consider their absence as being ready
2580 */
2581 return 1;
2582 }
2583}
2584
2542/** 2585/**
2543 * of_clk_init() - Scan and init clock providers from the DT 2586 * of_clk_init() - Scan and init clock providers from the DT
2544 * @matches: array of compatible values and init functions for providers. 2587 * @matches: array of compatible values and init functions for providers.
2545 * 2588 *
2546 * This function scans the device tree for matching clock providers and 2589 * This function scans the device tree for matching clock providers
2547 * calls their initialization functions 2590 * and calls their initialization functions. It also do it by trying
2591 * to follow the dependencies.
2548 */ 2592 */
2549void __init of_clk_init(const struct of_device_id *matches) 2593void __init of_clk_init(const struct of_device_id *matches)
2550{ 2594{
2551 const struct of_device_id *match; 2595 const struct of_device_id *match;
2552 struct device_node *np; 2596 struct device_node *np;
2597 struct clock_provider *clk_provider, *next;
2598 bool is_init_done;
2599 bool force = false;
2553 2600
2554 if (!matches) 2601 if (!matches)
2555 matches = &__clk_of_table; 2602 matches = &__clk_of_table;
2556 2603
2604 /* First prepare the list of the clocks providers */
2557 for_each_matching_node_and_match(np, matches, &match) { 2605 for_each_matching_node_and_match(np, matches, &match) {
2558 of_clk_init_cb_t clk_init_cb = match->data; 2606 struct clock_provider *parent =
2559 clk_init_cb(np); 2607 kzalloc(sizeof(struct clock_provider), GFP_KERNEL);
2608
2609 parent->clk_init_cb = match->data;
2610 parent->np = np;
2611 list_add(&parent->node, &clk_provider_list);
2612 }
2613
2614 while (!list_empty(&clk_provider_list)) {
2615 is_init_done = false;
2616 list_for_each_entry_safe(clk_provider, next,
2617 &clk_provider_list, node) {
2618 if (force || parent_ready(clk_provider->np)) {
2619 clk_provider->clk_init_cb(clk_provider->np);
2620 list_del(&clk_provider->node);
2621 kfree(clk_provider);
2622 is_init_done = true;
2623 }
2624 }
2625
2626 /*
2627 * We didn't managed to initialize any of the
2628 * remaining providers during the last loop, so now we
2629 * initialize all the remaining ones unconditionally
2630 * in case the clock parent was not mandatory
2631 */
2632 if (!is_init_done)
2633 force = true;
2634
2560 } 2635 }
2561} 2636}
2562#endif 2637#endif