aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/clock.c')
-rw-r--r--arch/sh/kernel/cpu/clock.c28
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
128void __clk_disable(struct clk *clk) 129void __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
136void clk_disable(struct clk *clk) 142void 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
169int clk_set_rate(struct clk *clk, unsigned long rate) 184int clk_set_rate(struct clk *clk, unsigned long rate)
170{ 185{
186 return clk_set_rate_ex(clk, rate, 0);
187}
188
189int 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);
298EXPORT_SYMBOL_GPL(clk_get_rate); 317EXPORT_SYMBOL_GPL(clk_get_rate);
299EXPORT_SYMBOL_GPL(clk_set_rate); 318EXPORT_SYMBOL_GPL(clk_set_rate);
300EXPORT_SYMBOL_GPL(clk_recalc_rate); 319EXPORT_SYMBOL_GPL(clk_recalc_rate);
320EXPORT_SYMBOL_GPL(clk_set_rate_ex);