Root/
1 | /* |
2 | * arch/arm/plat-spear/clock.c |
3 | * |
4 | * Clock framework for SPEAr platform |
5 | * |
6 | * Copyright (C) 2009 ST Microelectronics |
7 | * Viresh Kumar<viresh.kumar@st.com> |
8 | * |
9 | * This file is licensed under the terms of the GNU General Public |
10 | * License version 2. This program is licensed "as is" without any |
11 | * warranty of any kind, whether express or implied. |
12 | */ |
13 | |
14 | #include <linux/bug.h> |
15 | #include <linux/err.h> |
16 | #include <linux/io.h> |
17 | #include <linux/list.h> |
18 | #include <linux/module.h> |
19 | #include <linux/spinlock.h> |
20 | #include <mach/misc_regs.h> |
21 | #include <plat/clock.h> |
22 | |
23 | static DEFINE_SPINLOCK(clocks_lock); |
24 | static LIST_HEAD(root_clks); |
25 | |
26 | static void propagate_rate(struct list_head *); |
27 | |
28 | static int generic_clk_enable(struct clk *clk) |
29 | { |
30 | unsigned int val; |
31 | |
32 | if (!clk->en_reg) |
33 | return -EFAULT; |
34 | |
35 | val = readl(clk->en_reg); |
36 | if (unlikely(clk->flags & RESET_TO_ENABLE)) |
37 | val &= ~(1 << clk->en_reg_bit); |
38 | else |
39 | val |= 1 << clk->en_reg_bit; |
40 | |
41 | writel(val, clk->en_reg); |
42 | |
43 | return 0; |
44 | } |
45 | |
46 | static void generic_clk_disable(struct clk *clk) |
47 | { |
48 | unsigned int val; |
49 | |
50 | if (!clk->en_reg) |
51 | return; |
52 | |
53 | val = readl(clk->en_reg); |
54 | if (unlikely(clk->flags & RESET_TO_ENABLE)) |
55 | val |= 1 << clk->en_reg_bit; |
56 | else |
57 | val &= ~(1 << clk->en_reg_bit); |
58 | |
59 | writel(val, clk->en_reg); |
60 | } |
61 | |
62 | /* generic clk ops */ |
63 | static struct clkops generic_clkops = { |
64 | .enable = generic_clk_enable, |
65 | .disable = generic_clk_disable, |
66 | }; |
67 | |
68 | /* |
69 | * clk_enable - inform the system when the clock source should be running. |
70 | * @clk: clock source |
71 | * |
72 | * If the clock can not be enabled/disabled, this should return success. |
73 | * |
74 | * Returns success (0) or negative errno. |
75 | */ |
76 | int clk_enable(struct clk *clk) |
77 | { |
78 | unsigned long flags; |
79 | int ret = 0; |
80 | |
81 | if (!clk || IS_ERR(clk)) |
82 | return -EFAULT; |
83 | |
84 | spin_lock_irqsave(&clocks_lock, flags); |
85 | if (clk->usage_count == 0) { |
86 | if (clk->ops && clk->ops->enable) |
87 | ret = clk->ops->enable(clk); |
88 | } |
89 | clk->usage_count++; |
90 | spin_unlock_irqrestore(&clocks_lock, flags); |
91 | |
92 | return ret; |
93 | } |
94 | EXPORT_SYMBOL(clk_enable); |
95 | |
96 | /* |
97 | * clk_disable - inform the system when the clock source is no longer required. |
98 | * @clk: clock source |
99 | * |
100 | * Inform the system that a clock source is no longer required by |
101 | * a driver and may be shut down. |
102 | * |
103 | * Implementation detail: if the clock source is shared between |
104 | * multiple drivers, clk_enable() calls must be balanced by the |
105 | * same number of clk_disable() calls for the clock source to be |
106 | * disabled. |
107 | */ |
108 | void clk_disable(struct clk *clk) |
109 | { |
110 | unsigned long flags; |
111 | |
112 | if (!clk || IS_ERR(clk)) |
113 | return; |
114 | |
115 | WARN_ON(clk->usage_count == 0); |
116 | |
117 | spin_lock_irqsave(&clocks_lock, flags); |
118 | clk->usage_count--; |
119 | if (clk->usage_count == 0) { |
120 | if (clk->ops && clk->ops->disable) |
121 | clk->ops->disable(clk); |
122 | } |
123 | spin_unlock_irqrestore(&clocks_lock, flags); |
124 | } |
125 | EXPORT_SYMBOL(clk_disable); |
126 | |
127 | /** |
128 | * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. |
129 | * This is only valid once the clock source has been enabled. |
130 | * @clk: clock source |
131 | */ |
132 | unsigned long clk_get_rate(struct clk *clk) |
133 | { |
134 | unsigned long flags, rate; |
135 | |
136 | spin_lock_irqsave(&clocks_lock, flags); |
137 | rate = clk->rate; |
138 | spin_unlock_irqrestore(&clocks_lock, flags); |
139 | |
140 | return rate; |
141 | } |
142 | EXPORT_SYMBOL(clk_get_rate); |
143 | |
144 | /** |
145 | * clk_set_parent - set the parent clock source for this clock |
146 | * @clk: clock source |
147 | * @parent: parent clock source |
148 | * |
149 | * Returns success (0) or negative errno. |
150 | */ |
151 | int clk_set_parent(struct clk *clk, struct clk *parent) |
152 | { |
153 | int i, found = 0, val = 0; |
154 | unsigned long flags; |
155 | |
156 | if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent)) |
157 | return -EFAULT; |
158 | if (clk->usage_count) |
159 | return -EBUSY; |
160 | if (!clk->pclk_sel) |
161 | return -EPERM; |
162 | if (clk->pclk == parent) |
163 | return 0; |
164 | |
165 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { |
166 | if (clk->pclk_sel->pclk_info[i].pclk == parent) { |
167 | found = 1; |
168 | break; |
169 | } |
170 | } |
171 | |
172 | if (!found) |
173 | return -EINVAL; |
174 | |
175 | spin_lock_irqsave(&clocks_lock, flags); |
176 | /* reflect parent change in hardware */ |
177 | val = readl(clk->pclk_sel->pclk_sel_reg); |
178 | val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); |
179 | val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift; |
180 | writel(val, clk->pclk_sel->pclk_sel_reg); |
181 | spin_unlock_irqrestore(&clocks_lock, flags); |
182 | |
183 | /* reflect parent change in software */ |
184 | clk->recalc(clk); |
185 | propagate_rate(&clk->children); |
186 | return 0; |
187 | } |
188 | EXPORT_SYMBOL(clk_set_parent); |
189 | |
190 | /* registers clock in platform clock framework */ |
191 | void clk_register(struct clk_lookup *cl) |
192 | { |
193 | struct clk *clk = cl->clk; |
194 | unsigned long flags; |
195 | |
196 | if (!clk || IS_ERR(clk)) |
197 | return; |
198 | |
199 | spin_lock_irqsave(&clocks_lock, flags); |
200 | |
201 | INIT_LIST_HEAD(&clk->children); |
202 | if (clk->flags & ALWAYS_ENABLED) |
203 | clk->ops = NULL; |
204 | else if (!clk->ops) |
205 | clk->ops = &generic_clkops; |
206 | |
207 | /* root clock don't have any parents */ |
208 | if (!clk->pclk && !clk->pclk_sel) { |
209 | list_add(&clk->sibling, &root_clks); |
210 | /* add clocks with only one parent to parent's children list */ |
211 | } else if (clk->pclk && !clk->pclk_sel) { |
212 | list_add(&clk->sibling, &clk->pclk->children); |
213 | } else { |
214 | /* add clocks with > 1 parent to 1st parent's children list */ |
215 | list_add(&clk->sibling, |
216 | &clk->pclk_sel->pclk_info[0].pclk->children); |
217 | } |
218 | spin_unlock_irqrestore(&clocks_lock, flags); |
219 | |
220 | /* add clock to arm clockdev framework */ |
221 | clkdev_add(cl); |
222 | } |
223 | |
224 | /** |
225 | * propagate_rate - recalculate and propagate all clocks in list head |
226 | * |
227 | * Recalculates all root clocks in list head, which if the clock's .recalc is |
228 | * set correctly, should also propagate their rates. |
229 | */ |
230 | static void propagate_rate(struct list_head *lhead) |
231 | { |
232 | struct clk *clkp, *_temp; |
233 | |
234 | list_for_each_entry_safe(clkp, _temp, lhead, sibling) { |
235 | if (clkp->recalc) |
236 | clkp->recalc(clkp); |
237 | propagate_rate(&clkp->children); |
238 | } |
239 | } |
240 | |
241 | /* returns current programmed clocks clock info structure */ |
242 | static struct pclk_info *pclk_info_get(struct clk *clk) |
243 | { |
244 | unsigned int mask, i; |
245 | unsigned long flags; |
246 | struct pclk_info *info = NULL; |
247 | |
248 | spin_lock_irqsave(&clocks_lock, flags); |
249 | mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) |
250 | & clk->pclk_sel->pclk_sel_mask; |
251 | |
252 | for (i = 0; i < clk->pclk_sel->pclk_count; i++) { |
253 | if (clk->pclk_sel->pclk_info[i].pclk_mask == mask) |
254 | info = &clk->pclk_sel->pclk_info[i]; |
255 | } |
256 | spin_unlock_irqrestore(&clocks_lock, flags); |
257 | |
258 | return info; |
259 | } |
260 | |
261 | /* |
262 | * Set pclk as cclk's parent and add clock sibling node to current parents |
263 | * children list |
264 | */ |
265 | static void change_parent(struct clk *cclk, struct clk *pclk) |
266 | { |
267 | unsigned long flags; |
268 | |
269 | spin_lock_irqsave(&clocks_lock, flags); |
270 | list_del(&cclk->sibling); |
271 | list_add(&cclk->sibling, &pclk->children); |
272 | |
273 | cclk->pclk = pclk; |
274 | spin_unlock_irqrestore(&clocks_lock, flags); |
275 | } |
276 | |
277 | /* |
278 | * calculates current programmed rate of pll1 |
279 | * |
280 | * In normal mode |
281 | * rate = (2 * M[15:8] * Fin)/(N * 2^P) |
282 | * |
283 | * In Dithered mode |
284 | * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) |
285 | */ |
286 | void pll1_clk_recalc(struct clk *clk) |
287 | { |
288 | struct pll_clk_config *config = clk->private_data; |
289 | unsigned int num = 2, den = 0, val, mode = 0; |
290 | unsigned long flags; |
291 | |
292 | spin_lock_irqsave(&clocks_lock, flags); |
293 | mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) & |
294 | PLL_MODE_MASK; |
295 | |
296 | val = readl(config->cfg_reg); |
297 | /* calculate denominator */ |
298 | den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; |
299 | den = 1 << den; |
300 | den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; |
301 | |
302 | /* calculate numerator & denominator */ |
303 | if (!mode) { |
304 | /* Normal mode */ |
305 | num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; |
306 | } else { |
307 | /* Dithered mode */ |
308 | num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; |
309 | den *= 256; |
310 | } |
311 | |
312 | clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; |
313 | spin_unlock_irqrestore(&clocks_lock, flags); |
314 | } |
315 | |
316 | /* calculates current programmed rate of ahb or apb bus */ |
317 | void bus_clk_recalc(struct clk *clk) |
318 | { |
319 | struct bus_clk_config *config = clk->private_data; |
320 | unsigned int div; |
321 | unsigned long flags; |
322 | |
323 | spin_lock_irqsave(&clocks_lock, flags); |
324 | div = ((readl(config->reg) >> config->shift) & config->mask) + 1; |
325 | clk->rate = (unsigned long)clk->pclk->rate / div; |
326 | spin_unlock_irqrestore(&clocks_lock, flags); |
327 | } |
328 | |
329 | /* |
330 | * calculates current programmed rate of auxiliary synthesizers |
331 | * used by: UART, FIRDA |
332 | * |
333 | * Fout from synthesizer can be given from two equations: |
334 | * Fout1 = (Fin * X/Y)/2 |
335 | * Fout2 = Fin * X/Y |
336 | * |
337 | * Selection of eqn 1 or 2 is programmed in register |
338 | */ |
339 | void aux_clk_recalc(struct clk *clk) |
340 | { |
341 | struct aux_clk_config *config = clk->private_data; |
342 | struct pclk_info *pclk_info = NULL; |
343 | unsigned int num = 1, den = 1, val, eqn; |
344 | unsigned long flags; |
345 | |
346 | /* get current programmed parent */ |
347 | pclk_info = pclk_info_get(clk); |
348 | if (!pclk_info) { |
349 | spin_lock_irqsave(&clocks_lock, flags); |
350 | clk->pclk = NULL; |
351 | clk->rate = 0; |
352 | spin_unlock_irqrestore(&clocks_lock, flags); |
353 | return; |
354 | } |
355 | |
356 | change_parent(clk, pclk_info->pclk); |
357 | |
358 | spin_lock_irqsave(&clocks_lock, flags); |
359 | if (pclk_info->scalable) { |
360 | val = readl(config->synth_reg); |
361 | |
362 | eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK; |
363 | if (eqn == AUX_EQ1_SEL) |
364 | den *= 2; |
365 | |
366 | /* calculate numerator */ |
367 | num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK; |
368 | |
369 | /* calculate denominator */ |
370 | den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK; |
371 | val = (((clk->pclk->rate/10000) * num) / den) * 10000; |
372 | } else |
373 | val = clk->pclk->rate; |
374 | |
375 | clk->rate = val; |
376 | spin_unlock_irqrestore(&clocks_lock, flags); |
377 | } |
378 | |
379 | /* |
380 | * calculates current programmed rate of gpt synthesizers |
381 | * Fout from synthesizer can be given from below equations: |
382 | * Fout= Fin/((2 ^ (N+1)) * (M+1)) |
383 | */ |
384 | void gpt_clk_recalc(struct clk *clk) |
385 | { |
386 | struct aux_clk_config *config = clk->private_data; |
387 | struct pclk_info *pclk_info = NULL; |
388 | unsigned int div = 1, val; |
389 | unsigned long flags; |
390 | |
391 | pclk_info = pclk_info_get(clk); |
392 | if (!pclk_info) { |
393 | spin_lock_irqsave(&clocks_lock, flags); |
394 | clk->pclk = NULL; |
395 | clk->rate = 0; |
396 | spin_unlock_irqrestore(&clocks_lock, flags); |
397 | return; |
398 | } |
399 | |
400 | change_parent(clk, pclk_info->pclk); |
401 | |
402 | spin_lock_irqsave(&clocks_lock, flags); |
403 | if (pclk_info->scalable) { |
404 | val = readl(config->synth_reg); |
405 | div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK; |
406 | div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1); |
407 | } |
408 | |
409 | clk->rate = (unsigned long)clk->pclk->rate / div; |
410 | spin_unlock_irqrestore(&clocks_lock, flags); |
411 | } |
412 | |
413 | /* |
414 | * Used for clocks that always have same value as the parent clock divided by a |
415 | * fixed divisor |
416 | */ |
417 | void follow_parent(struct clk *clk) |
418 | { |
419 | unsigned long flags; |
420 | |
421 | spin_lock_irqsave(&clocks_lock, flags); |
422 | clk->rate = clk->pclk->rate; |
423 | spin_unlock_irqrestore(&clocks_lock, flags); |
424 | } |
425 | |
426 | /** |
427 | * recalc_root_clocks - recalculate and propagate all root clocks |
428 | * |
429 | * Recalculates all root clocks (clocks with no parent), which if the |
430 | * clock's .recalc is set correctly, should also propagate their rates. |
431 | */ |
432 | void recalc_root_clocks(void) |
433 | { |
434 | propagate_rate(&root_clks); |
435 | } |
436 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9