diff options
Diffstat (limited to 'arch/sh/kernel/cpu/clock.c')
-rw-r--r-- | arch/sh/kernel/cpu/clock.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index abb586b12565..2075f90d76c7 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -98,13 +98,14 @@ int __clk_enable(struct clk *clk) | |||
98 | if (clk->ops && clk->ops->init) | 98 | if (clk->ops && clk->ops->init) |
99 | clk->ops->init(clk); | 99 | clk->ops->init(clk); |
100 | 100 | ||
101 | kref_get(&clk->kref); | ||
102 | |||
101 | if (clk->flags & CLK_ALWAYS_ENABLED) | 103 | if (clk->flags & CLK_ALWAYS_ENABLED) |
102 | return 0; | 104 | return 0; |
103 | 105 | ||
104 | if (likely(clk->ops && clk->ops->enable)) | 106 | if (likely(clk->ops && clk->ops->enable)) |
105 | clk->ops->enable(clk); | 107 | clk->ops->enable(clk); |
106 | 108 | ||
107 | kref_get(&clk->kref); | ||
108 | return 0; | 109 | return 0; |
109 | } | 110 | } |
110 | 111 | ||
@@ -127,10 +128,15 @@ static void clk_kref_release(struct kref *kref) | |||
127 | 128 | ||
128 | void __clk_disable(struct clk *clk) | 129 | void __clk_disable(struct clk *clk) |
129 | { | 130 | { |
131 | int count = kref_put(&clk->kref, clk_kref_release); | ||
132 | |||
130 | if (clk->flags & CLK_ALWAYS_ENABLED) | 133 | if (clk->flags & CLK_ALWAYS_ENABLED) |
131 | return; | 134 | return; |
132 | 135 | ||
133 | kref_put(&clk->kref, clk_kref_release); | 136 | if (!count) { /* count reaches zero, disable the clock */ |
137 | if (likely(clk->ops && clk->ops->disable)) | ||
138 | clk->ops->disable(clk); | ||
139 | } | ||
134 | } | 140 | } |
135 | 141 | ||
136 | void clk_disable(struct clk *clk) | 142 | void clk_disable(struct clk *clk) |
@@ -151,6 +157,15 @@ int clk_register(struct clk *clk) | |||
151 | 157 | ||
152 | mutex_unlock(&clock_list_sem); | 158 | mutex_unlock(&clock_list_sem); |
153 | 159 | ||
160 | if (clk->flags & CLK_ALWAYS_ENABLED) { | ||
161 | pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name); | ||
162 | if (clk->ops && clk->ops->init) | ||
163 | clk->ops->init(clk); | ||
164 | if (clk->ops && clk->ops->enable) | ||
165 | clk->ops->enable(clk); | ||
166 | pr_debug( "Enabled."); | ||
167 | } | ||
168 | |||
154 | return 0; | 169 | return 0; |
155 | } | 170 | } |
156 | 171 | ||
@@ -168,13 +183,18 @@ inline unsigned long clk_get_rate(struct clk *clk) | |||
168 | 183 | ||
169 | int clk_set_rate(struct clk *clk, unsigned long rate) | 184 | int clk_set_rate(struct clk *clk, unsigned long rate) |
170 | { | 185 | { |
186 | return clk_set_rate_ex(clk, rate, 0); | ||
187 | } | ||
188 | |||
189 | int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) | ||
190 | { | ||
171 | int ret = -EOPNOTSUPP; | 191 | int ret = -EOPNOTSUPP; |
172 | 192 | ||
173 | if (likely(clk->ops && clk->ops->set_rate)) { | 193 | if (likely(clk->ops && clk->ops->set_rate)) { |
174 | unsigned long flags; | 194 | unsigned long flags; |
175 | 195 | ||
176 | spin_lock_irqsave(&clock_lock, flags); | 196 | spin_lock_irqsave(&clock_lock, flags); |
177 | ret = clk->ops->set_rate(clk, rate); | 197 | ret = clk->ops->set_rate(clk, rate, algo_id); |
178 | spin_unlock_irqrestore(&clock_lock, flags); | 198 | spin_unlock_irqrestore(&clock_lock, flags); |
179 | } | 199 | } |
180 | 200 | ||
@@ -256,7 +276,6 @@ int __init clk_init(void) | |||
256 | 276 | ||
257 | arch_init_clk_ops(&clk->ops, i); | 277 | arch_init_clk_ops(&clk->ops, i); |
258 | ret |= clk_register(clk); | 278 | ret |= clk_register(clk); |
259 | clk_enable(clk); | ||
260 | } | 279 | } |
261 | 280 | ||
262 | /* Kick the child clocks.. */ | 281 | /* Kick the child clocks.. */ |
@@ -298,3 +317,4 @@ EXPORT_SYMBOL_GPL(__clk_disable); | |||
298 | EXPORT_SYMBOL_GPL(clk_get_rate); | 317 | EXPORT_SYMBOL_GPL(clk_get_rate); |
299 | EXPORT_SYMBOL_GPL(clk_set_rate); | 318 | EXPORT_SYMBOL_GPL(clk_set_rate); |
300 | EXPORT_SYMBOL_GPL(clk_recalc_rate); | 319 | EXPORT_SYMBOL_GPL(clk_recalc_rate); |
320 | EXPORT_SYMBOL_GPL(clk_set_rate_ex); | ||