diff options
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 46 |
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); |
3014 | out: | 3024 | out: |
3015 | clk_pm_runtime_put(core); | 3025 | clk_pm_runtime_put(core); |