aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clkt_clksel.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/clkt_clksel.c')
-rw-r--r--arch/arm/mach-omap2/clkt_clksel.c238
1 files changed, 0 insertions, 238 deletions
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 03ceb2efd532..0ec9f6fdf046 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -41,11 +41,7 @@
41 41
42#include <linux/kernel.h> 42#include <linux/kernel.h>
43#include <linux/errno.h> 43#include <linux/errno.h>
44#ifdef CONFIG_COMMON_CLK
45#include <linux/clk-provider.h> 44#include <linux/clk-provider.h>
46#else
47#include <linux/clk.h>
48#endif
49#include <linux/io.h> 45#include <linux/io.h>
50#include <linux/bug.h> 46#include <linux/bug.h>
51 47
@@ -62,11 +58,7 @@
62 * the element associated with the supplied parent clock address. 58 * the element associated with the supplied parent clock address.
63 * Returns a pointer to the struct clksel on success or NULL on error. 59 * Returns a pointer to the struct clksel on success or NULL on error.
64 */ 60 */
65#ifdef CONFIG_COMMON_CLK
66static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk, 61static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
67#else
68static const struct clksel *_get_clksel_by_parent(struct clk *clk,
69#endif
70 struct clk *src_clk) 62 struct clk *src_clk)
71{ 63{
72 const struct clksel *clks; 64 const struct clksel *clks;
@@ -81,11 +73,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
81 if (!clks->parent) { 73 if (!clks->parent) {
82 /* This indicates a data problem */ 74 /* This indicates a data problem */
83 WARN(1, "clock: %s: could not find parent clock %s in clksel array\n", 75 WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
84#ifdef CONFIG_COMMON_CLK
85 __clk_get_name(clk->hw.clk), __clk_get_name(src_clk)); 76 __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
86#else
87 __clk_get_name(clk), __clk_get_name(src_clk));
88#endif
89 return NULL; 77 return NULL;
90 } 78 }
91 79
@@ -93,66 +81,6 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
93} 81}
94 82
95/** 83/**
96 * _get_div_and_fieldval() - find the new clksel divisor and field value to use
97 * @src_clk: planned new parent struct clk *
98 * @clk: struct clk * that is being reparented
99 * @field_val: pointer to a u32 to contain the register data for the divisor
100 *
101 * Given an intended new parent struct clk * @src_clk, and the struct
102 * clk * @clk to the clock that is being reparented, find the
103 * appropriate rate divisor for the new clock (returned as the return
104 * value), and the corresponding register bitfield data to program to
105 * reach that divisor (returned in the u32 pointed to by @field_val).
106 * Returns 0 on error, or returns the newly-selected divisor upon
107 * success (in this latter case, the corresponding register bitfield
108 * value is passed back in the variable pointed to by @field_val)
109 */
110#ifndef CONFIG_COMMON_CLK
111static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
112 u32 *field_val)
113{
114 const struct clksel *clks;
115 const struct clksel_rate *clkr, *max_clkr = NULL;
116 u8 max_div = 0;
117
118 clks = _get_clksel_by_parent(clk, src_clk);
119 if (!clks)
120 return 0;
121
122 /*
123 * Find the highest divisor (e.g., the one resulting in the
124 * lowest rate) to use as the default. This should avoid
125 * clock rates that are too high for the device. XXX A better
126 * solution here would be to try to determine if there is a
127 * divisor matching the original clock rate before the parent
128 * switch, and if it cannot be found, to fall back to the
129 * highest divisor.
130 */
131 for (clkr = clks->rates; clkr->div; clkr++) {
132 if (!(clkr->flags & cpu_mask))
133 continue;
134
135 if (clkr->div > max_div) {
136 max_div = clkr->div;
137 max_clkr = clkr;
138 }
139 }
140
141 if (max_div == 0) {
142 /* This indicates an error in the clksel data */
143 WARN(1, "clock: %s: could not find divisor for parent %s\n",
144 __clk_get_name(clk),
145 __clk_get_name(__clk_get_parent(src_clk)));
146 return 0;
147 }
148
149 *field_val = max_clkr->val;
150
151 return max_div;
152}
153#endif
154
155/**
156 * _write_clksel_reg() - program a clock's clksel register in hardware 84 * _write_clksel_reg() - program a clock's clksel register in hardware
157 * @clk: struct clk * to program 85 * @clk: struct clk * to program
158 * @v: clksel bitfield value to program (with LSB at bit 0) 86 * @v: clksel bitfield value to program (with LSB at bit 0)
@@ -165,11 +93,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
165 * take into account any time the hardware might take to switch the 93 * take into account any time the hardware might take to switch the
166 * clock source. 94 * clock source.
167 */ 95 */
168#ifdef CONFIG_COMMON_CLK
169static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val) 96static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
170#else
171static void _write_clksel_reg(struct clk *clk, u32 field_val)
172#endif
173{ 97{
174 u32 v; 98 u32 v;
175 99
@@ -192,21 +116,13 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
192 * before calling. Returns 0 on error or returns the actual integer divisor 116 * before calling. Returns 0 on error or returns the actual integer divisor
193 * upon success. 117 * upon success.
194 */ 118 */
195#ifdef CONFIG_COMMON_CLK
196static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val) 119static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
197#else
198static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
199#endif
200{ 120{
201 const struct clksel *clks; 121 const struct clksel *clks;
202 const struct clksel_rate *clkr; 122 const struct clksel_rate *clkr;
203 struct clk *parent; 123 struct clk *parent;
204 124
205#ifdef CONFIG_COMMON_CLK
206 parent = __clk_get_parent(clk->hw.clk); 125 parent = __clk_get_parent(clk->hw.clk);
207#else
208 parent = __clk_get_parent(clk);
209#endif
210 126
211 clks = _get_clksel_by_parent(clk, parent); 127 clks = _get_clksel_by_parent(clk, parent);
212 if (!clks) 128 if (!clks)
@@ -223,12 +139,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
223 if (!clkr->div) { 139 if (!clkr->div) {
224 /* This indicates a data error */ 140 /* This indicates a data error */
225 WARN(1, "clock: %s: could not find fieldval %d for parent %s\n", 141 WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
226#ifdef CONFIG_COMMON_CLK
227 __clk_get_name(clk->hw.clk), field_val, 142 __clk_get_name(clk->hw.clk), field_val,
228 __clk_get_name(parent)); 143 __clk_get_name(parent));
229#else
230 __clk_get_name(clk), field_val, __clk_get_name(parent));
231#endif
232 return 0; 144 return 0;
233 } 145 }
234 146
@@ -245,11 +157,7 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
245 * register field value _before_ left-shifting (i.e., LSB is at bit 157 * register field value _before_ left-shifting (i.e., LSB is at bit
246 * 0); or returns 0xFFFFFFFF (~0) upon error. 158 * 0); or returns 0xFFFFFFFF (~0) upon error.
247 */ 159 */
248#ifdef CONFIG_COMMON_CLK
249static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div) 160static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
250#else
251static u32 _divisor_to_clksel(struct clk *clk, u32 div)
252#endif
253{ 161{
254 const struct clksel *clks; 162 const struct clksel *clks;
255 const struct clksel_rate *clkr; 163 const struct clksel_rate *clkr;
@@ -258,11 +166,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
258 /* should never happen */ 166 /* should never happen */
259 WARN_ON(div == 0); 167 WARN_ON(div == 0);
260 168
261#ifdef CONFIG_COMMON_CLK
262 parent = __clk_get_parent(clk->hw.clk); 169 parent = __clk_get_parent(clk->hw.clk);
263#else
264 parent = __clk_get_parent(clk);
265#endif
266 clks = _get_clksel_by_parent(clk, parent); 170 clks = _get_clksel_by_parent(clk, parent);
267 if (!clks) 171 if (!clks)
268 return ~0; 172 return ~0;
@@ -277,12 +181,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
277 181
278 if (!clkr->div) { 182 if (!clkr->div) {
279 pr_err("clock: %s: could not find divisor %d for parent %s\n", 183 pr_err("clock: %s: could not find divisor %d for parent %s\n",
280#ifdef CONFIG_COMMON_CLK
281 __clk_get_name(clk->hw.clk), div, 184 __clk_get_name(clk->hw.clk), div,
282 __clk_get_name(parent)); 185 __clk_get_name(parent));
283#else
284 __clk_get_name(clk), div, __clk_get_name(parent));
285#endif
286 return ~0; 186 return ~0;
287 } 187 }
288 188
@@ -297,11 +197,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
297 * into the hardware, convert it into the actual divisor value, and 197 * into the hardware, convert it into the actual divisor value, and
298 * return it; or return 0 on error. 198 * return it; or return 0 on error.
299 */ 199 */
300#ifdef CONFIG_COMMON_CLK
301static u32 _read_divisor(struct clk_hw_omap *clk) 200static u32 _read_divisor(struct clk_hw_omap *clk)
302#else
303static u32 _read_divisor(struct clk *clk)
304#endif
305{ 201{
306 u32 v; 202 u32 v;
307 203
@@ -329,12 +225,8 @@ static u32 _read_divisor(struct clk *clk)
329 * 225 *
330 * Returns the rounded clock rate or returns 0xffffffff on error. 226 * Returns the rounded clock rate or returns 0xffffffff on error.
331 */ 227 */
332#ifdef CONFIG_COMMON_CLK
333u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk, 228u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
334 unsigned long target_rate, 229 unsigned long target_rate,
335#else
336u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
337#endif
338 u32 *new_div) 230 u32 *new_div)
339{ 231{
340 unsigned long test_rate; 232 unsigned long test_rate;
@@ -345,13 +237,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
345 unsigned long parent_rate; 237 unsigned long parent_rate;
346 const char *clk_name; 238 const char *clk_name;
347 239
348#ifdef CONFIG_COMMON_CLK
349 parent = __clk_get_parent(clk->hw.clk); 240 parent = __clk_get_parent(clk->hw.clk);
350 clk_name = __clk_get_name(clk->hw.clk); 241 clk_name = __clk_get_name(clk->hw.clk);
351#else
352 parent = __clk_get_parent(clk);
353 clk_name = __clk_get_name(clk);
354#endif
355 parent_rate = __clk_get_rate(parent); 242 parent_rate = __clk_get_rate(parent);
356 243
357 if (!clk->clksel || !clk->clksel_mask) 244 if (!clk->clksel || !clk->clksel_mask)
@@ -402,7 +289,6 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
402 * (i.e., those used in struct clk field function pointers, etc.) 289 * (i.e., those used in struct clk field function pointers, etc.)
403 */ 290 */
404 291
405#ifdef CONFIG_COMMON_CLK
406/** 292/**
407 * omap2_clksel_find_parent_index() - return the array index of the current 293 * omap2_clksel_find_parent_index() - return the array index of the current
408 * hardware parent of @hw 294 * hardware parent of @hw
@@ -457,62 +343,6 @@ u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
457 return ret; 343 return ret;
458} 344}
459 345
460#else
461
462/**
463 * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
464 * @clk: OMAP clock struct ptr to use
465 *
466 * Given a pointer @clk to a source-selectable struct clk, read the
467 * hardware register and determine what its parent is currently set
468 * to. Update @clk's .parent field with the appropriate clk ptr. No
469 * return value.
470 */
471void omap2_init_clksel_parent(struct clk *clk)
472{
473 const struct clksel *clks;
474 const struct clksel_rate *clkr;
475 u32 r, found = 0;
476 struct clk *parent;
477 const char *clk_name;
478
479 if (!clk->clksel || !clk->clksel_mask)
480 return;
481
482 parent = __clk_get_parent(clk);
483 clk_name = __clk_get_name(clk);
484
485 r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
486 r >>= __ffs(clk->clksel_mask);
487
488 for (clks = clk->clksel; clks->parent && !found; clks++) {
489 for (clkr = clks->rates; clkr->div && !found; clkr++) {
490 if (!(clkr->flags & cpu_mask))
491 continue;
492
493 if (clkr->val == r) {
494 if (parent != clks->parent) {
495 pr_debug("clock: %s: inited parent to %s (was %s)\n",
496 clk_name,
497 __clk_get_name(clks->parent),
498 ((parent) ?
499 __clk_get_name(parent) :
500 "NULL"));
501 clk_reparent(clk, clks->parent);
502 }
503 found = 1;
504 }
505 }
506 }
507
508 /* This indicates a data error */
509 WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
510 clk_name, r);
511
512 return;
513}
514
515#endif
516 346
517/** 347/**
518 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field 348 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
@@ -523,7 +353,6 @@ void omap2_init_clksel_parent(struct clk *clk)
523 * function. Returns the clock's current rate, based on its parent's rate 353 * function. Returns the clock's current rate, based on its parent's rate
524 * and its current divisor setting in the hardware. 354 * and its current divisor setting in the hardware.
525 */ 355 */
526#ifdef CONFIG_COMMON_CLK
527unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate) 356unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
528{ 357{
529 unsigned long rate; 358 unsigned long rate;
@@ -544,26 +373,6 @@ unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
544 373
545 return rate; 374 return rate;
546} 375}
547#else
548unsigned long omap2_clksel_recalc(struct clk *clk)
549{
550 unsigned long rate;
551 u32 div = 0;
552 struct clk *parent;
553
554 div = _read_divisor(clk);
555 if (div == 0)
556 return __clk_get_rate(clk);
557
558 parent = __clk_get_parent(clk);
559 rate = __clk_get_rate(parent) / div;
560
561 pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
562 __clk_get_name(clk), rate, div);
563
564 return rate;
565}
566#endif
567 376
568/** 377/**
569 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate 378 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
@@ -576,15 +385,10 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
576 * 385 *
577 * Returns the rounded clock rate or returns 0xffffffff on error. 386 * Returns the rounded clock rate or returns 0xffffffff on error.
578 */ 387 */
579#ifdef CONFIG_COMMON_CLK
580long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate, 388long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
581 unsigned long *parent_rate) 389 unsigned long *parent_rate)
582{ 390{
583 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 391 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
584#else
585long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
586{
587#endif
588 u32 new_div; 392 u32 new_div;
589 393
590 return omap2_clksel_round_rate_div(clk, target_rate, &new_div); 394 return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
@@ -605,15 +409,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
605 * is changed, they will all be affected without any notification. 409 * is changed, they will all be affected without any notification.
606 * Returns -EINVAL upon error, or 0 upon success. 410 * Returns -EINVAL upon error, or 0 upon success.
607 */ 411 */
608#ifdef CONFIG_COMMON_CLK
609int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate, 412int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
610 unsigned long parent_rate) 413 unsigned long parent_rate)
611{ 414{
612 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 415 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
613#else
614int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
615{
616#endif
617 u32 field_val, validrate, new_div = 0; 416 u32 field_val, validrate, new_div = 0;
618 417
619 if (!clk->clksel || !clk->clksel_mask) 418 if (!clk->clksel || !clk->clksel_mask)
@@ -629,15 +428,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
629 428
630 _write_clksel_reg(clk, field_val); 429 _write_clksel_reg(clk, field_val);
631 430
632#ifdef CONFIG_COMMON_CLK
633 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk), 431 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
634 __clk_get_rate(hw->clk)); 432 __clk_get_rate(hw->clk));
635#else
636 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
637 __clk_get_rate(clk));
638
639 clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
640#endif
641 433
642 return 0; 434 return 0;
643} 435}
@@ -662,7 +454,6 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
662 * affected without any notification. Returns -EINVAL upon error, or 454 * affected without any notification. Returns -EINVAL upon error, or
663 * 0 upon success. 455 * 0 upon success.
664 */ 456 */
665#ifdef CONFIG_COMMON_CLK
666int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val) 457int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
667{ 458{
668 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 459 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
@@ -673,32 +464,3 @@ int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
673 _write_clksel_reg(clk, field_val); 464 _write_clksel_reg(clk, field_val);
674 return 0; 465 return 0;
675} 466}
676#else
677int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
678{
679 u32 field_val = 0;
680 u32 parent_div;
681
682 if (!clk->clksel || !clk->clksel_mask)
683 return -EINVAL;
684
685 parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
686 if (!parent_div)
687 return -EINVAL;
688 _write_clksel_reg(clk, field_val);
689
690 clk_reparent(clk, new_parent);
691
692 /* CLKSEL clocks follow their parents' rates, divided by a divisor */
693 clk->rate = __clk_get_rate(new_parent);
694
695 if (parent_div > 0)
696 __clk_get_rate(clk) /= parent_div;
697 pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
698 __clk_get_name(clk),
699 __clk_get_name(__clk_get_parent(clk)),
700 __clk_get_rate(clk));
701
702 return 0;
703}
704#endif