aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorMartin Fuzzey <mfuzzey@parkeon.com>2012-11-22 14:15:05 -0500
committerMike Turquette <mturquette@linaro.org>2012-11-26 14:14:45 -0500
commit1f61e5f143b578606389887887af549bc5554353 (patch)
treeb49a23716e8896eac027f2730a4cf0d94983ec4f /drivers/clk
parent45228ef32240957b1536fbba1ca12377cb2e587c (diff)
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 <mfuzzey@parkeon.com> Signed-off-by: Mike Turquette <mturquette@linaro.org> [mturquette@linaro.org: improve $SUBJECT]
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk.c10
1 files changed, 9 insertions, 1 deletions
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)
1298 * walk the list of orphan clocks and reparent any that are children of 1298 * walk the list of orphan clocks and reparent any that are children of
1299 * this clock 1299 * this clock
1300 */ 1300 */
1301 hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) 1301 hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) {
1302 if (orphan->ops->get_parent) {
1303 i = orphan->ops->get_parent(orphan->hw);
1304 if (!strcmp(clk->name, orphan->parent_names[i]))
1305 __clk_reparent(orphan, clk);
1306 continue;
1307 }
1308
1302 for (i = 0; i < orphan->num_parents; i++) 1309 for (i = 0; i < orphan->num_parents; i++)
1303 if (!strcmp(clk->name, orphan->parent_names[i])) { 1310 if (!strcmp(clk->name, orphan->parent_names[i])) {
1304 __clk_reparent(orphan, clk); 1311 __clk_reparent(orphan, clk);
1305 break; 1312 break;
1306 } 1313 }
1314 }
1307 1315
1308 /* 1316 /*
1309 * optional platform-specific magic 1317 * optional platform-specific magic