From 1f61e5f143b578606389887887af549bc5554353 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Thu, 22 Nov 2012 20:15:05 +0100 Subject: clk: clock multiplexers may register out of order When a clock, C is initialised any orphan clocks listing C as a possible parent are reparented to it regardless of the parent requested by the orphan's get_parent() operation. This means that multiplexers registered before their parents are reparented to the first parent subsequently declared, regardless of the selection made by the hardware registers. For example: static const char *sel[] = { "srcA", "srcB", "dummy", "srcC" }; child = clk_register_mux(NULL, "child", sel, ARRAY_SIZE(sel), ...); clk_register_fixed(NULL, "dummy", ...); clk_register_fixed(NULL, "srcA", ...); clk_register_fixed(NULL, "srcB", ...); clk_register_fixed(NULL, "srcC", ...); Causes child's parent to always be "dummy". To fix this, when an orphanned clock has a get_parent() operation, only reparent to the clock indicated by get_parent(). Signed-off-by: Martin Fuzzey Signed-off-by: Mike Turquette [mturquette@linaro.org: improve $SUBJECT] --- drivers/clk/clk.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2fd28ddd06c..9955ad7e786 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1298,12 +1298,20 @@ int __clk_init(struct device *dev, struct clk *clk) * walk the list of orphan clocks and reparent any that are children of * this clock */ - hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) + hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) { + if (orphan->ops->get_parent) { + i = orphan->ops->get_parent(orphan->hw); + if (!strcmp(clk->name, orphan->parent_names[i])) + __clk_reparent(orphan, clk); + continue; + } + for (i = 0; i < orphan->num_parents; i++) if (!strcmp(clk->name, orphan->parent_names[i])) { __clk_reparent(orphan, clk); break; } + } /* * optional platform-specific magic -- cgit v1.2.3-70-g09d2