summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r--drivers/clk/clk.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0f686a9dac3e..076d4244d672 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1125,8 +1125,10 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
1125{ 1125{
1126 lockdep_assert_held(&prepare_lock); 1126 lockdep_assert_held(&prepare_lock);
1127 1127
1128 if (!core) 1128 if (!core) {
1129 req->rate = 0;
1129 return 0; 1130 return 0;
1131 }
1130 1132
1131 clk_core_init_rate_req(core, req); 1133 clk_core_init_rate_req(core, req);
1132 1134
@@ -2309,8 +2311,11 @@ static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
2309 2311
2310 trace_clk_set_phase(core, degrees); 2312 trace_clk_set_phase(core, degrees);
2311 2313
2312 if (core->ops->set_phase) 2314 if (core->ops->set_phase) {
2313 ret = core->ops->set_phase(core->hw, degrees); 2315 ret = core->ops->set_phase(core->hw, degrees);
2316 if (!ret)
2317 core->phase = degrees;
2318 }
2314 2319
2315 trace_clk_set_phase_complete(core, degrees); 2320 trace_clk_set_phase_complete(core, degrees);
2316 2321
@@ -2968,22 +2973,37 @@ static int __clk_core_init(struct clk_core *core)
2968 core->rate = core->req_rate = rate; 2973 core->rate = core->req_rate = rate;
2969 2974
2970 /* 2975 /*
2976 * Enable CLK_IS_CRITICAL clocks so newly added critical clocks
2977 * don't get accidentally disabled when walking the orphan tree and
2978 * reparenting clocks
2979 */
2980 if (core->flags & CLK_IS_CRITICAL) {
2981 unsigned long flags;
2982
2983 clk_core_prepare(core);
2984
2985 flags = clk_enable_lock();
2986 clk_core_enable(core);
2987 clk_enable_unlock(flags);
2988 }
2989
2990 /*
2971 * walk the list of orphan clocks and reparent any that newly finds a 2991 * walk the list of orphan clocks and reparent any that newly finds a
2972 * parent. 2992 * parent.
2973 */ 2993 */
2974 hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { 2994 hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
2975 struct clk_core *parent = __clk_init_parent(orphan); 2995 struct clk_core *parent = __clk_init_parent(orphan);
2976 unsigned long flags;
2977 2996
2978 /* 2997 /*
2979 * we could call __clk_set_parent, but that would result in a 2998 * We need to use __clk_set_parent_before() and _after() to
2980 * redundant call to the .set_rate op, if it exists 2999 * to properly migrate any prepare/enable count of the orphan
3000 * clock. This is important for CLK_IS_CRITICAL clocks, which
3001 * are enabled during init but might not have a parent yet.
2981 */ 3002 */
2982 if (parent) { 3003 if (parent) {
2983 /* update the clk tree topology */ 3004 /* update the clk tree topology */
2984 flags = clk_enable_lock(); 3005 __clk_set_parent_before(orphan, parent);
2985 clk_reparent(orphan, parent); 3006 __clk_set_parent_after(orphan, parent, NULL);
2986 clk_enable_unlock(flags);
2987 __clk_recalc_accuracies(orphan); 3007 __clk_recalc_accuracies(orphan);
2988 __clk_recalc_rates(orphan, 0); 3008 __clk_recalc_rates(orphan, 0);
2989 } 3009 }
@@ -3000,16 +3020,6 @@ static int __clk_core_init(struct clk_core *core)
3000 if (core->ops->init) 3020 if (core->ops->init)
3001 core->ops->init(core->hw); 3021 core->ops->init(core->hw);
3002 3022
3003 if (core->flags & CLK_IS_CRITICAL) {
3004 unsigned long flags;
3005
3006 clk_core_prepare(core);
3007
3008 flags = clk_enable_lock();
3009 clk_core_enable(core);
3010 clk_enable_unlock(flags);
3011 }
3012
3013 kref_init(&core->ref); 3023 kref_init(&core->ref);
3014out: 3024out:
3015 clk_pm_runtime_put(core); 3025 clk_pm_runtime_put(core);