aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clkt_clksel.c
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2012-11-10 18:58:41 -0500
committerPaul Walmsley <paul@pwsan.com>2012-11-12 15:55:50 -0500
commit32cc002116b866151ca24c6e9110ba8a93754753 (patch)
tree4a7d3f08bf774ed72d37bd0de541d9dac5e3083e /arch/arm/mach-omap2/clkt_clksel.c
parentf5dd3bb53ca45f3b47c6889e5920c562f5a37359 (diff)
ARM: OMAP4: clock: Convert to common clk
Convert all OMAP4 specific platform files to use COMMON clk and keep all the changes under the CONFIG_COMMON_CLK macro check so it does not break any existing code. At a later point switch to COMMON clk and get rid of all old/legacy code. This converts all apis which will be called directly from COMMON clk to take a struct clk_hw parameter, and all the internal platform apis to take a struct clk_hw_omap parameter. Changes are based off the original patch from Mike Turquette. Signed-off-by: Rajendra Nayak <rnayak@ti.com> [paul@pwsan.com: created new omap2_clksel_find_parent_index() rather than modifying omap2_init_clksel_parent(); moved clkhwops_iclk_wait to clkt_iclk.c to fix OMAP4-only builds; added clk-provider.h include to clock.h to try to fix some 3430-builds] [mturquette@ti.com: squash patch for omap2_clkops_{en,dis}able_clkdm; omap2_dflt_clk_is_enabled should not enable clocks] Signed-off-by: Mike Turquette <mturquette@ti.com> [paul@pwsan.com: fix compiler warning; update to apply; added kerneldoc on non-trivial new functions; added the dpll3xxx clockdomain modifications] Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/clkt_clksel.c')
-rw-r--r--arch/arm/mach-omap2/clkt_clksel.c184
1 files changed, 179 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 53646facda45..03ceb2efd532 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -41,7 +41,11 @@
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>
46#else
44#include <linux/clk.h> 47#include <linux/clk.h>
48#endif
45#include <linux/io.h> 49#include <linux/io.h>
46#include <linux/bug.h> 50#include <linux/bug.h>
47 51
@@ -58,11 +62,18 @@
58 * the element associated with the supplied parent clock address. 62 * the element associated with the supplied parent clock address.
59 * Returns a pointer to the struct clksel on success or NULL on error. 63 * Returns a pointer to the struct clksel on success or NULL on error.
60 */ 64 */
65#ifdef CONFIG_COMMON_CLK
66static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
67#else
61static const struct clksel *_get_clksel_by_parent(struct clk *clk, 68static const struct clksel *_get_clksel_by_parent(struct clk *clk,
69#endif
62 struct clk *src_clk) 70 struct clk *src_clk)
63{ 71{
64 const struct clksel *clks; 72 const struct clksel *clks;
65 73
74 if (!src_clk)
75 return NULL;
76
66 for (clks = clk->clksel; clks->parent; clks++) 77 for (clks = clk->clksel; clks->parent; clks++)
67 if (clks->parent == src_clk) 78 if (clks->parent == src_clk)
68 break; /* Found the requested parent */ 79 break; /* Found the requested parent */
@@ -70,7 +81,11 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
70 if (!clks->parent) { 81 if (!clks->parent) {
71 /* This indicates a data problem */ 82 /* This indicates a data problem */
72 WARN(1, "clock: %s: could not find parent clock %s in clksel array\n", 83 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));
86#else
73 __clk_get_name(clk), __clk_get_name(src_clk)); 87 __clk_get_name(clk), __clk_get_name(src_clk));
88#endif
74 return NULL; 89 return NULL;
75 } 90 }
76 91
@@ -92,6 +107,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
92 * success (in this latter case, the corresponding register bitfield 107 * success (in this latter case, the corresponding register bitfield
93 * value is passed back in the variable pointed to by @field_val) 108 * value is passed back in the variable pointed to by @field_val)
94 */ 109 */
110#ifndef CONFIG_COMMON_CLK
95static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk, 111static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
96 u32 *field_val) 112 u32 *field_val)
97{ 113{
@@ -134,6 +150,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
134 150
135 return max_div; 151 return max_div;
136} 152}
153#endif
137 154
138/** 155/**
139 * _write_clksel_reg() - program a clock's clksel register in hardware 156 * _write_clksel_reg() - program a clock's clksel register in hardware
@@ -148,7 +165,11 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
148 * take into account any time the hardware might take to switch the 165 * take into account any time the hardware might take to switch the
149 * clock source. 166 * clock source.
150 */ 167 */
168#ifdef CONFIG_COMMON_CLK
169static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
170#else
151static void _write_clksel_reg(struct clk *clk, u32 field_val) 171static void _write_clksel_reg(struct clk *clk, u32 field_val)
172#endif
152{ 173{
153 u32 v; 174 u32 v;
154 175
@@ -171,13 +192,22 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
171 * before calling. Returns 0 on error or returns the actual integer divisor 192 * before calling. Returns 0 on error or returns the actual integer divisor
172 * upon success. 193 * upon success.
173 */ 194 */
195#ifdef CONFIG_COMMON_CLK
196static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
197#else
174static u32 _clksel_to_divisor(struct clk *clk, u32 field_val) 198static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
199#endif
175{ 200{
176 const struct clksel *clks; 201 const struct clksel *clks;
177 const struct clksel_rate *clkr; 202 const struct clksel_rate *clkr;
178 struct clk *parent; 203 struct clk *parent;
179 204
205#ifdef CONFIG_COMMON_CLK
206 parent = __clk_get_parent(clk->hw.clk);
207#else
180 parent = __clk_get_parent(clk); 208 parent = __clk_get_parent(clk);
209#endif
210
181 clks = _get_clksel_by_parent(clk, parent); 211 clks = _get_clksel_by_parent(clk, parent);
182 if (!clks) 212 if (!clks)
183 return 0; 213 return 0;
@@ -193,7 +223,12 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
193 if (!clkr->div) { 223 if (!clkr->div) {
194 /* This indicates a data error */ 224 /* This indicates a data error */
195 WARN(1, "clock: %s: could not find fieldval %d for parent %s\n", 225 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,
228 __clk_get_name(parent));
229#else
196 __clk_get_name(clk), field_val, __clk_get_name(parent)); 230 __clk_get_name(clk), field_val, __clk_get_name(parent));
231#endif
197 return 0; 232 return 0;
198 } 233 }
199 234
@@ -210,7 +245,11 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
210 * register field value _before_ left-shifting (i.e., LSB is at bit 245 * register field value _before_ left-shifting (i.e., LSB is at bit
211 * 0); or returns 0xFFFFFFFF (~0) upon error. 246 * 0); or returns 0xFFFFFFFF (~0) upon error.
212 */ 247 */
248#ifdef CONFIG_COMMON_CLK
249static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
250#else
213static u32 _divisor_to_clksel(struct clk *clk, u32 div) 251static u32 _divisor_to_clksel(struct clk *clk, u32 div)
252#endif
214{ 253{
215 const struct clksel *clks; 254 const struct clksel *clks;
216 const struct clksel_rate *clkr; 255 const struct clksel_rate *clkr;
@@ -219,7 +258,11 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
219 /* should never happen */ 258 /* should never happen */
220 WARN_ON(div == 0); 259 WARN_ON(div == 0);
221 260
261#ifdef CONFIG_COMMON_CLK
262 parent = __clk_get_parent(clk->hw.clk);
263#else
222 parent = __clk_get_parent(clk); 264 parent = __clk_get_parent(clk);
265#endif
223 clks = _get_clksel_by_parent(clk, parent); 266 clks = _get_clksel_by_parent(clk, parent);
224 if (!clks) 267 if (!clks)
225 return ~0; 268 return ~0;
@@ -234,7 +277,12 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
234 277
235 if (!clkr->div) { 278 if (!clkr->div) {
236 pr_err("clock: %s: could not find divisor %d for parent %s\n", 279 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,
282 __clk_get_name(parent));
283#else
237 __clk_get_name(clk), div, __clk_get_name(parent)); 284 __clk_get_name(clk), div, __clk_get_name(parent));
285#endif
238 return ~0; 286 return ~0;
239 } 287 }
240 288
@@ -249,7 +297,11 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
249 * into the hardware, convert it into the actual divisor value, and 297 * into the hardware, convert it into the actual divisor value, and
250 * return it; or return 0 on error. 298 * return it; or return 0 on error.
251 */ 299 */
300#ifdef CONFIG_COMMON_CLK
301static u32 _read_divisor(struct clk_hw_omap *clk)
302#else
252static u32 _read_divisor(struct clk *clk) 303static u32 _read_divisor(struct clk *clk)
304#endif
253{ 305{
254 u32 v; 306 u32 v;
255 307
@@ -277,7 +329,12 @@ static u32 _read_divisor(struct clk *clk)
277 * 329 *
278 * Returns the rounded clock rate or returns 0xffffffff on error. 330 * Returns the rounded clock rate or returns 0xffffffff on error.
279 */ 331 */
332#ifdef CONFIG_COMMON_CLK
333u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
334 unsigned long target_rate,
335#else
280u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate, 336u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
337#endif
281 u32 *new_div) 338 u32 *new_div)
282{ 339{
283 unsigned long test_rate; 340 unsigned long test_rate;
@@ -288,9 +345,14 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
288 unsigned long parent_rate; 345 unsigned long parent_rate;
289 const char *clk_name; 346 const char *clk_name;
290 347
348#ifdef CONFIG_COMMON_CLK
349 parent = __clk_get_parent(clk->hw.clk);
350 clk_name = __clk_get_name(clk->hw.clk);
351#else
291 parent = __clk_get_parent(clk); 352 parent = __clk_get_parent(clk);
292 parent_rate = __clk_get_rate(parent);
293 clk_name = __clk_get_name(clk); 353 clk_name = __clk_get_name(clk);
354#endif
355 parent_rate = __clk_get_rate(parent);
294 356
295 if (!clk->clksel || !clk->clksel_mask) 357 if (!clk->clksel || !clk->clksel_mask)
296 return ~0; 358 return ~0;
@@ -340,6 +402,63 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
340 * (i.e., those used in struct clk field function pointers, etc.) 402 * (i.e., those used in struct clk field function pointers, etc.)
341 */ 403 */
342 404
405#ifdef CONFIG_COMMON_CLK
406/**
407 * omap2_clksel_find_parent_index() - return the array index of the current
408 * hardware parent of @hw
409 * @hw: struct clk_hw * to find the current hardware parent of
410 *
411 * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
412 * clk_hw_omap record representing a source-selectable hardware clock,
413 * read the hardware register and determine what its parent is
414 * currently set to. Intended to be called only by the common clock
415 * framework struct clk_hw_ops.get_parent function pointer. Return
416 * the array index of this parent clock upon success -- there is no
417 * way to return an error, so if we encounter an error, just WARN()
418 * and pretend that we know that we're doing.
419 */
420u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
421{
422 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
423 const struct clksel *clks;
424 const struct clksel_rate *clkr;
425 u32 r, found = 0;
426 struct clk *parent;
427 const char *clk_name;
428 int ret = 0, f = 0;
429
430 parent = __clk_get_parent(hw->clk);
431 clk_name = __clk_get_name(hw->clk);
432
433 /* XXX should be able to return an error */
434 WARN((!clk->clksel || !clk->clksel_mask),
435 "clock: %s: attempt to call on a non-clksel clock", clk_name);
436
437 r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
438 r >>= __ffs(clk->clksel_mask);
439
440 for (clks = clk->clksel; clks->parent && !found; clks++) {
441 for (clkr = clks->rates; clkr->div && !found; clkr++) {
442 if (!(clkr->flags & cpu_mask))
443 continue;
444
445 if (clkr->val == r) {
446 found = 1;
447 ret = f;
448 }
449 }
450 f++;
451 }
452
453 /* This indicates a data error */
454 WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
455 clk_name, r);
456
457 return ret;
458}
459
460#else
461
343/** 462/**
344 * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr 463 * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
345 * @clk: OMAP clock struct ptr to use 464 * @clk: OMAP clock struct ptr to use
@@ -393,6 +512,8 @@ void omap2_init_clksel_parent(struct clk *clk)
393 return; 512 return;
394} 513}
395 514
515#endif
516
396/** 517/**
397 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field 518 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
398 * @clk: struct clk * 519 * @clk: struct clk *
@@ -402,6 +523,28 @@ void omap2_init_clksel_parent(struct clk *clk)
402 * function. Returns the clock's current rate, based on its parent's rate 523 * function. Returns the clock's current rate, based on its parent's rate
403 * and its current divisor setting in the hardware. 524 * and its current divisor setting in the hardware.
404 */ 525 */
526#ifdef CONFIG_COMMON_CLK
527unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
528{
529 unsigned long rate;
530 u32 div = 0;
531 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
532
533 if (!parent_rate)
534 return 0;
535
536 div = _read_divisor(clk);
537 if (!div)
538 rate = parent_rate;
539 else
540 rate = parent_rate / div;
541
542 pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
543 __clk_get_name(hw->clk), rate, div);
544
545 return rate;
546}
547#else
405unsigned long omap2_clksel_recalc(struct clk *clk) 548unsigned long omap2_clksel_recalc(struct clk *clk)
406{ 549{
407 unsigned long rate; 550 unsigned long rate;
@@ -420,6 +563,7 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
420 563
421 return rate; 564 return rate;
422} 565}
566#endif
423 567
424/** 568/**
425 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate 569 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
@@ -432,8 +576,15 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
432 * 576 *
433 * Returns the rounded clock rate or returns 0xffffffff on error. 577 * Returns the rounded clock rate or returns 0xffffffff on error.
434 */ 578 */
579#ifdef CONFIG_COMMON_CLK
580long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
581 unsigned long *parent_rate)
582{
583 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
584#else
435long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate) 585long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
436{ 586{
587#endif
437 u32 new_div; 588 u32 new_div;
438 589
439 return omap2_clksel_round_rate_div(clk, target_rate, &new_div); 590 return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
@@ -454,8 +605,15 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
454 * is changed, they will all be affected without any notification. 605 * is changed, they will all be affected without any notification.
455 * Returns -EINVAL upon error, or 0 upon success. 606 * Returns -EINVAL upon error, or 0 upon success.
456 */ 607 */
608#ifdef CONFIG_COMMON_CLK
609int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
610 unsigned long parent_rate)
611{
612 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
613#else
457int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) 614int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
458{ 615{
616#endif
459 u32 field_val, validrate, new_div = 0; 617 u32 field_val, validrate, new_div = 0;
460 618
461 if (!clk->clksel || !clk->clksel_mask) 619 if (!clk->clksel || !clk->clksel_mask)
@@ -471,11 +629,16 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
471 629
472 _write_clksel_reg(clk, field_val); 630 _write_clksel_reg(clk, field_val);
473 631
474 clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div; 632#ifdef CONFIG_COMMON_CLK
475 633 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
634 __clk_get_rate(hw->clk));
635#else
476 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk), 636 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
477 __clk_get_rate(clk)); 637 __clk_get_rate(clk));
478 638
639 clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
640#endif
641
479 return 0; 642 return 0;
480} 643}
481 644
@@ -499,6 +662,18 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
499 * affected without any notification. Returns -EINVAL upon error, or 662 * affected without any notification. Returns -EINVAL upon error, or
500 * 0 upon success. 663 * 0 upon success.
501 */ 664 */
665#ifdef CONFIG_COMMON_CLK
666int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
667{
668 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
669
670 if (!clk->clksel || !clk->clksel_mask)
671 return -EINVAL;
672
673 _write_clksel_reg(clk, field_val);
674 return 0;
675}
676#else
502int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent) 677int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
503{ 678{
504 u32 field_val = 0; 679 u32 field_val = 0;
@@ -510,7 +685,6 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
510 parent_div = _get_div_and_fieldval(new_parent, clk, &field_val); 685 parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
511 if (!parent_div) 686 if (!parent_div)
512 return -EINVAL; 687 return -EINVAL;
513
514 _write_clksel_reg(clk, field_val); 688 _write_clksel_reg(clk, field_val);
515 689
516 clk_reparent(clk, new_parent); 690 clk_reparent(clk, new_parent);
@@ -520,7 +694,6 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
520 694
521 if (parent_div > 0) 695 if (parent_div > 0)
522 __clk_get_rate(clk) /= parent_div; 696 __clk_get_rate(clk) /= parent_div;
523
524 pr_debug("clock: %s: set parent to %s (new rate %ld)\n", 697 pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
525 __clk_get_name(clk), 698 __clk_get_name(clk),
526 __clk_get_name(__clk_get_parent(clk)), 699 __clk_get_name(__clk_get_parent(clk)),
@@ -528,3 +701,4 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
528 701
529 return 0; 702 return 0;
530} 703}
704#endif