]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/clock.c
ARM: OMAP2: New DPLL clock framework
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / clock.c
1 /*
2  *  linux/arch/arm/mach-omap2/clock.c
3  *
4  *  Copyright (C) 2005-2008 Texas Instruments, Inc.
5  *  Copyright (C) 2004-2008 Nokia Corporation
6  *
7  *  Contacts:
8  *  Richard Woodruff <r-woodruff2@ti.com>
9  *  Paul Walmsley
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 #undef DEBUG
16
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/device.h>
20 #include <linux/list.h>
21 #include <linux/errno.h>
22 #include <linux/delay.h>
23 #include <linux/clk.h>
24
25 #include <asm/io.h>
26
27 #include <asm/arch/clock.h>
28 #include <asm/arch/sram.h>
29 #include <asm/arch/cpu.h>
30 #include <asm/div64.h>
31
32 #include "memory.h"
33 #include "sdrc.h"
34 #include "clock.h"
35 #include "prm.h"
36 #include "prm-regbits-24xx.h"
37 #include "cm.h"
38 #include "cm-regbits-24xx.h"
39 #include "cm-regbits-34xx.h"
40
41 #define MAX_CLOCK_ENABLE_WAIT           100000
42
43 u8 cpu_mask;
44
45 /*-------------------------------------------------------------------------
46  * Omap2 specific clock functions
47  *-------------------------------------------------------------------------*/
48
49 u8 mask_to_shift(u32 mask)
50 {
51         return ffs(mask) - 1;
52 }
53
54 /**
55  * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
56  * @clk: OMAP clock struct ptr to use
57  *
58  * Given a pointer to a source-selectable struct clk, read the hardware
59  * register and determine what its parent is currently set to.  Update the
60  * clk->parent field with the appropriate clk ptr.
61  */
62 void omap2_init_clksel_parent(struct clk *clk)
63 {
64         const struct clksel *clks;
65         const struct clksel_rate *clkr;
66         u32 r, found = 0;
67
68         if (!clk->clksel)
69                 return;
70
71         r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
72         r >>= mask_to_shift(clk->clksel_mask);
73
74         for (clks = clk->clksel; clks->parent && !found; clks++) {
75                 for (clkr = clks->rates; clkr->div && !found; clkr++) {
76                         if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
77                                 if (clk->parent != clks->parent) {
78                                         pr_debug("clock: inited %s parent "
79                                                  "to %s (was %s)\n",
80                                                  clk->name, clks->parent->name,
81                                                  ((clk->parent) ?
82                                                   clk->parent->name : "NULL"));
83                                         clk->parent = clks->parent;
84                                 };
85                                 found = 1;
86                         }
87                 }
88         }
89
90         if (!found)
91                 printk(KERN_ERR "clock: init parent: could not find "
92                        "regval %0x for clock %s\n", r,  clk->name);
93
94         return;
95 }
96
97 /* Returns the DPLL rate */
98 u32 omap2_get_dpll_rate(struct clk *clk)
99 {
100         long long dpll_clk;
101         u32 dpll_mult, dpll_div, dpll;
102         const struct dpll_data *dd;
103
104         dd = clk->dpll_data;
105         /* REVISIT: What do we return on error? */
106         if (!dd)
107                 return 0;
108
109         dpll = cm_read_reg(dd->mult_div1_reg);
110         dpll_mult = dpll & dd->mult_mask;
111         dpll_mult >>= mask_to_shift(dd->mult_mask);
112         dpll_div = dpll & dd->div1_mask;
113         dpll_div >>= mask_to_shift(dd->div1_mask);
114
115         dpll_clk = (long long)clk->parent->rate * dpll_mult;
116         do_div(dpll_clk, dpll_div + 1);
117
118         return dpll_clk;
119 }
120
121 /*
122  * Used for clocks that have the same value as the parent clock,
123  * divided by some factor
124  */
125 void omap2_fixed_divisor_recalc(struct clk *clk)
126 {
127         WARN_ON(!clk->fixed_div);
128
129         clk->rate = clk->parent->rate / clk->fixed_div;
130
131         if (clk->flags & RATE_PROPAGATES)
132                 propagate_rate(clk);
133 }
134
135 /**
136  * omap2_wait_clock_ready - wait for clock to enable
137  * @reg: physical address of clock IDLEST register
138  * @mask: value to mask against to determine if the clock is active
139  * @name: name of the clock (for printk)
140  *
141  * Returns 1 if the clock enabled in time, or 0 if it failed to enable
142  * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
143  */
144 int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
145 {
146         int i = 0;
147         int ena = 0;
148
149         /*
150          * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
151          * 34xx reverses this, just to keep us on our toes
152          */
153         if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) {
154                 ena = mask;
155         } else if (cpu_mask & RATE_IN_343X) {
156                 ena = 0;
157         }
158
159         /* Wait for lock */
160         while (((cm_read_reg(reg) & mask) != ena) &&
161                (i++ < MAX_CLOCK_ENABLE_WAIT)) {
162                 udelay(1);
163         }
164
165         if (i < MAX_CLOCK_ENABLE_WAIT)
166                 pr_debug("Clock %s stable after %d loops\n", name, i);
167         else
168                 printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
169                        name, MAX_CLOCK_ENABLE_WAIT);
170
171
172         return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
173 };
174
175
176 /*
177  * Note: We don't need special code here for INVERT_ENABLE
178  * for the time being since INVERT_ENABLE only applies to clocks enabled by
179  * CM_CLKEN_PLL
180  */
181 static void omap2_clk_wait_ready(struct clk *clk)
182 {
183         void __iomem *reg, *other_reg, *st_reg;
184         u32 bit;
185
186         /*
187          * REVISIT: This code is pretty ugly.  It would be nice to generalize
188          * it and pull it into struct clk itself somehow.
189          */
190         reg = clk->enable_reg;
191         if ((((u32)reg & 0xff) >= CM_FCLKEN1) &&
192             (((u32)reg & 0xff) <= OMAP24XX_CM_FCLKEN2))
193                 other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */
194         else if ((((u32)reg & 0xff) >= CM_ICLKEN1) &&
195                  (((u32)reg & 0xff) <= OMAP24XX_CM_ICLKEN4))
196                 other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */
197         else
198                 return;
199
200         /* REVISIT: What are the appropriate exclusions for 34XX? */
201         /* No check for DSS or cam clocks */
202         if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
203                 if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
204                     clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
205                     clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
206                         return;
207         }
208
209         /* REVISIT: What are the appropriate exclusions for 34XX? */
210         /* OMAP3: ignore DSS-mod clocks */
211         if (cpu_is_omap34xx() &&
212             (((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(OMAP3430_DSS_MOD, 0)))
213                 return;
214
215         /* Check if both functional and interface clocks
216          * are running. */
217         bit = 1 << clk->enable_bit;
218         if (!(cm_read_reg(other_reg) & bit))
219                 return;
220         st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
221
222         omap2_wait_clock_ready(st_reg, bit, clk->name);
223 }
224
225 /* Enables clock without considering parent dependencies or use count
226  * REVISIT: Maybe change this to use clk->enable like on omap1?
227  */
228 int _omap2_clk_enable(struct clk *clk)
229 {
230         u32 regval32;
231
232         if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
233                 return 0;
234
235         if (clk->enable)
236                 return clk->enable(clk);
237
238         if (unlikely(clk->enable_reg == 0)) {
239                 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
240                        clk->name);
241                 return 0; /* REVISIT: -EINVAL */
242         }
243
244         regval32 = cm_read_reg(clk->enable_reg);
245         if (clk->flags & INVERT_ENABLE)
246                 regval32 &= ~(1 << clk->enable_bit);
247         else
248                 regval32 |= (1 << clk->enable_bit);
249         cm_write_reg(regval32, clk->enable_reg);
250         wmb();
251
252         omap2_clk_wait_ready(clk);
253
254         return 0;
255 }
256
257 /* Disables clock without considering parent dependencies or use count */
258 void _omap2_clk_disable(struct clk *clk)
259 {
260         u32 regval32;
261
262         if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
263                 return;
264
265         if (clk->disable) {
266                 clk->disable(clk);
267                 return;
268         }
269
270         if (clk->enable_reg == 0) {
271                 /*
272                  * 'Independent' here refers to a clock which is not
273                  * controlled by its parent.
274                  */
275                 printk(KERN_ERR "clock: clk_disable called on independent "
276                        "clock %s which has no enable_reg\n", clk->name);
277                 return;
278         }
279
280         regval32 = cm_read_reg(clk->enable_reg);
281         if (clk->flags & INVERT_ENABLE)
282                 regval32 |= (1 << clk->enable_bit);
283         else
284                 regval32 &= ~(1 << clk->enable_bit);
285         cm_write_reg(regval32, clk->enable_reg);
286         wmb();
287 }
288
289 void omap2_clk_disable(struct clk *clk)
290 {
291         if (clk->usecount > 0 && !(--clk->usecount)) {
292                 _omap2_clk_disable(clk);
293                 if (likely((u32)clk->parent))
294                         omap2_clk_disable(clk->parent);
295         }
296 }
297
298 int omap2_clk_enable(struct clk *clk)
299 {
300         int ret = 0;
301
302         if (clk->usecount++ == 0) {
303                 if (likely((u32)clk->parent))
304                         ret = omap2_clk_enable(clk->parent);
305
306                 if (unlikely(ret != 0)) {
307                         clk->usecount--;
308                         return ret;
309                 }
310
311                 ret = _omap2_clk_enable(clk);
312
313                 if (unlikely(ret != 0) && clk->parent) {
314                         omap2_clk_disable(clk->parent);
315                         clk->usecount--;
316                 }
317         }
318
319         return ret;
320 }
321
322 /*
323  * Used for clocks that are part of CLKSEL_xyz governed clocks.
324  * REVISIT: Maybe change to use clk->enable() functions like on omap1?
325  */
326 void omap2_clksel_recalc(struct clk *clk)
327 {
328         u32 div = 0;
329
330         pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
331
332         div = omap2_clksel_get_divisor(clk);
333         if (div == 0)
334                 return;
335
336         if (unlikely(clk->rate == clk->parent->rate / div))
337                 return;
338         clk->rate = clk->parent->rate / div;
339
340         pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
341
342         if (unlikely(clk->flags & RATE_PROPAGATES))
343                 propagate_rate(clk);
344 }
345
346 /**
347  * omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
348  * @clk: OMAP struct clk ptr to inspect
349  * @src_clk: OMAP struct clk ptr of the parent clk to search for
350  *
351  * Scan the struct clksel array associated with the clock to find
352  * the element associated with the supplied parent clock address.
353  * Returns a pointer to the struct clksel on success or NULL on error.
354  */
355 const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
356                                                 struct clk *src_clk)
357 {
358         const struct clksel *clks;
359
360         if (!clk->clksel)
361                 return NULL;
362
363         for (clks = clk->clksel; clks->parent; clks++) {
364                 if (clks->parent == src_clk)
365                         break; /* Found the requested parent */
366         }
367
368         if (!clks->parent) {
369                 printk(KERN_ERR "clock: Could not find parent clock %s in "
370                        "clksel array of clock %s\n", src_clk->name,
371                        clk->name);
372                 return NULL;
373         }
374
375         return clks;
376 }
377
378 /**
379  * omap2_clksel_round_rate_div - find divisor for the given clock and rate
380  * @clk: OMAP struct clk to use
381  * @target_rate: desired clock rate
382  * @new_div: ptr to where we should store the divisor
383  *
384  * Finds 'best' divider value in an array based on the source and target
385  * rates.  The divider array must be sorted with smallest divider first.
386  * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
387  * they are only settable as part of virtual_prcm set.
388  *
389  * Returns the rounded clock rate or returns 0xffffffff on error.
390  */
391 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
392                                 u32 *new_div)
393 {
394         unsigned long test_rate;
395         const struct clksel *clks;
396         const struct clksel_rate *clkr;
397         u32 last_div = 0;
398
399         printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n",
400                clk->name, target_rate);
401
402         *new_div = 1;
403
404         clks = omap2_get_clksel_by_parent(clk, clk->parent);
405         if (clks == NULL)
406                 return ~0;
407
408         for (clkr = clks->rates; clkr->div; clkr++) {
409                 if (!(clkr->flags & cpu_mask))
410                     continue;
411
412                 /* Sanity check */
413                 if (clkr->div <= last_div)
414                         printk(KERN_ERR "clock: clksel_rate table not sorted "
415                                "for clock %s", clk->name);
416
417                 last_div = clkr->div;
418
419                 test_rate = clk->parent->rate / clkr->div;
420
421                 if (test_rate <= target_rate)
422                         break; /* found it */
423         }
424
425         if (!clkr->div) {
426                 printk(KERN_ERR "clock: Could not find divisor for target "
427                        "rate %ld for clock %s parent %s\n", target_rate,
428                        clk->name, clk->parent->name);
429                 return ~0;
430         }
431
432         *new_div = clkr->div;
433
434         printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div,
435                (clk->parent->rate / clkr->div));
436
437         return (clk->parent->rate / clkr->div);
438 }
439
440 /**
441  * omap2_clksel_round_rate - find rounded rate for the given clock and rate
442  * @clk: OMAP struct clk to use
443  * @target_rate: desired clock rate
444  *
445  * Compatibility wrapper for OMAP clock framework
446  * Finds best target rate based on the source clock and possible dividers.
447  * rates. The divider array must be sorted with smallest divider first.
448  * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
449  * they are only settable as part of virtual_prcm set.
450  *
451  * Returns the rounded clock rate or returns 0xffffffff on error.
452  */
453 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
454 {
455         u32 new_div;
456
457         return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
458 }
459
460
461 /* Given a clock and a rate apply a clock specific rounding function */
462 long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
463 {
464         if (clk->round_rate != 0)
465                 return clk->round_rate(clk, rate);
466
467         if (clk->flags & RATE_FIXED)
468                 printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
469                        "on fixed-rate clock %s\n", clk->name);
470
471         return clk->rate;
472 }
473
474 /**
475  * omap2_clksel_to_divisor() - turn clksel field value into integer divider
476  * @clk: OMAP struct clk to use
477  * @field_val: register field value to find
478  *
479  * Given a struct clk of a rate-selectable clksel clock, and a register field
480  * value to search for, find the corresponding clock divisor.  The register
481  * field value should be pre-masked and shifted down so the LSB is at bit 0
482  * before calling.  Returns 0 on error
483  */
484 u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
485 {
486         const struct clksel *clks;
487         const struct clksel_rate *clkr;
488
489         clks = omap2_get_clksel_by_parent(clk, clk->parent);
490         if (clks == NULL)
491                 return 0;
492
493         for (clkr = clks->rates; clkr->div; clkr++) {
494                 if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
495                         break;
496         }
497
498         if (!clkr->div) {
499                 printk(KERN_ERR "clock: Could not find fieldval %d for "
500                        "clock %s parent %s\n", field_val, clk->name,
501                        clk->parent->name);
502                 return 0;
503         }
504
505         return clkr->div;
506 }
507
508 /**
509  * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
510  * @clk: OMAP struct clk to use
511  * @div: integer divisor to search for
512  *
513  * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
514  * find the corresponding register field value.  The return register value is
515  * the value before left-shifting.  Returns 0xffffffff on error
516  */
517 u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
518 {
519         const struct clksel *clks;
520         const struct clksel_rate *clkr;
521
522         /* should never happen */
523         WARN_ON(div == 0);
524
525         clks = omap2_get_clksel_by_parent(clk, clk->parent);
526         if (clks == NULL)
527                 return 0;
528
529         for (clkr = clks->rates; clkr->div; clkr++) {
530                 if ((clkr->flags & cpu_mask) && (clkr->div == div))
531                         break;
532         }
533
534         if (!clkr->div) {
535                 printk(KERN_ERR "clock: Could not find divisor %d for "
536                        "clock %s parent %s\n", div, clk->name,
537                        clk->parent->name);
538                 return 0;
539         }
540
541         return clkr->val;
542 }
543
544 /**
545  * omap2_get_clksel - find clksel register addr & field mask for a clk
546  * @clk: struct clk to use
547  * @field_mask: ptr to u32 to store the register field mask
548  *
549  * Returns the address of the clksel register upon success or NULL on error.
550  */
551 void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
552 {
553         if (unlikely((clk->clksel_reg == 0) || (clk->clksel_mask == 0)))
554                 return NULL;
555
556         *field_mask = clk->clksel_mask;
557
558         return clk->clksel_reg;
559 }
560
561 /**
562  * omap2_clksel_get_divisor - get current divider applied to parent clock.
563  * @clk: OMAP struct clk to use.
564  *
565  * Returns the integer divisor upon success or 0 on error.
566  */
567 u32 omap2_clksel_get_divisor(struct clk *clk)
568 {
569         u32 field_mask, field_val;
570         void __iomem *div_addr;
571
572         div_addr = omap2_get_clksel(clk, &field_mask);
573         if (div_addr == 0)
574                 return 0;
575
576         field_val = cm_read_reg(div_addr) & field_mask;
577         field_val >>= mask_to_shift(field_mask);
578
579         return omap2_clksel_to_divisor(clk, field_val);
580 }
581
582 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
583 {
584         u32 field_mask, field_val, reg_val, validrate, new_div = 0;
585         void __iomem *div_addr;
586
587         validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
588         if (validrate != rate)
589                 return -EINVAL;
590
591         div_addr = omap2_get_clksel(clk, &field_mask);
592         if (div_addr == 0)
593                 return -EINVAL;
594
595         field_val = omap2_divisor_to_clksel(clk, new_div);
596         if (field_val == ~0)
597                 return -EINVAL;
598
599         reg_val = cm_read_reg(div_addr);
600         reg_val &= ~field_mask;
601         reg_val |= (field_val << mask_to_shift(field_mask));
602         cm_write_reg(reg_val, div_addr);
603         wmb();
604
605         clk->rate = clk->parent->rate / new_div;
606
607         if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
608                 prm_write_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
609                 wmb();
610         }
611
612         return 0;
613 }
614
615
616 /* Set the clock rate for a clock source */
617 int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
618 {
619         int ret = -EINVAL;
620
621         pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
622
623         /* CONFIG_PARTICIPANT clocks are changed only in sets via the
624            rate table mechanism, driven by mpu_speed  */
625         if (clk->flags & CONFIG_PARTICIPANT)
626                 return -EINVAL;
627
628         /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
629         if (clk->set_rate != 0)
630                 ret = clk->set_rate(clk, rate);
631
632         if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
633                 propagate_rate(clk);
634
635         return ret;
636 }
637
638 /*
639  * Converts encoded control register address into a full address
640  * On error, *src_addr will be returned as 0.
641  */
642 static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
643                                       struct clk *src_clk, u32 *field_mask,
644                                       struct clk *clk, u32 *parent_div)
645 {
646         const struct clksel *clks;
647         const struct clksel_rate *clkr;
648
649         *parent_div = 0;
650         *src_addr = 0;
651
652         clks = omap2_get_clksel_by_parent(clk, src_clk);
653         if (clks == NULL)
654                 return 0;
655
656         for (clkr = clks->rates; clkr->div; clkr++) {
657                 if (clkr->flags & (cpu_mask | DEFAULT_RATE))
658                         break; /* Found the default rate for this platform */
659         }
660
661         if (!clkr->div) {
662                 printk(KERN_ERR "clock: Could not find default rate for "
663                        "clock %s parent %s\n", clk->name,
664                        src_clk->parent->name);
665                 return 0;
666         }
667
668         /* Should never happen.  Add a clksel mask to the struct clk. */
669         WARN_ON(clk->clksel_mask == 0);
670
671         *field_mask = clk->clksel_mask;
672         *src_addr = clk->clksel_reg;
673         *parent_div = clkr->div;
674
675         return clkr->val;
676 }
677
678 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
679 {
680         void __iomem *src_addr;
681         u32 field_val, field_mask, reg_val, parent_div;
682
683         if (unlikely(clk->flags & CONFIG_PARTICIPANT))
684                 return -EINVAL;
685
686         if (!clk->clksel)
687                 return -EINVAL;
688
689         field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
690                                                &field_mask, clk, &parent_div);
691         if (src_addr == 0)
692                 return -EINVAL;
693
694         if (clk->usecount > 0)
695                 _omap2_clk_disable(clk);
696
697         /* Set new source value (previous dividers if any in effect) */
698         reg_val = __raw_readl(src_addr) & ~field_mask;
699         reg_val |= (field_val << mask_to_shift(field_mask));
700         __raw_writel(reg_val, src_addr);
701         wmb();
702
703         if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
704                 prm_write_reg(OMAP24XX_VALID_CONFIG,
705                               OMAP24XX_PRCM_CLKCFG_CTRL);
706                 wmb();
707         }
708
709         if (clk->usecount > 0)
710                 _omap2_clk_enable(clk);
711
712         clk->parent = new_parent;
713
714         /* CLKSEL clocks follow their parents' rates, divided by a divisor */
715         clk->rate = new_parent->rate;
716
717         if (parent_div > 0)
718                 clk->rate /= parent_div;
719
720         pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
721                  clk->name, clk->parent->name, clk->rate);
722
723         if (unlikely(clk->flags & RATE_PROPAGATES))
724                 propagate_rate(clk);
725
726         return 0;
727 }
728
729 /*-------------------------------------------------------------------------
730  * Omap2 clock reset and init functions
731  *-------------------------------------------------------------------------*/
732
733 #ifdef CONFIG_OMAP_RESET_CLOCKS
734 void omap2_clk_disable_unused(struct clk *clk)
735 {
736         u32 regval32, v;
737
738         v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
739
740         regval32 = cm_read_reg(clk->enable_reg);
741         if ((regval32 & (1 << clk->enable_bit)) == v)
742                 return;
743
744         printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
745         _omap2_clk_disable(clk);
746 }
747 #endif