diff options
author | Tero Kristo <t-kristo@ti.com> | 2014-10-03 09:57:14 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2014-11-13 11:26:45 -0500 |
commit | 2e1a7b014f9c3d61fbf12b429f0479242264dbec (patch) | |
tree | cecb7c3739740f991c03eda4f0fbfd075458cd82 | |
parent | e3ab6013ab06d3a861ed00c1f8d32aa4e6b66ddd (diff) |
ARM: OMAP3+: DPLL: use determine_rate() and set_rate_and_parent()
Currently, DPLLs are hiding the gory details of switching parent
within set_rate, which confuses the common clock code and is wrong.
Fixed by applying the new determine_rate() and set_rate_and_parent()
functionality to any clock-ops previously using the broken approach.
This patch also removes the broken legacy code.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
-rw-r--r-- | arch/arm/mach-omap2/cclock3xxx_data.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/dpll3xxx.c | 96 | ||||
-rw-r--r-- | drivers/clk/ti/dpll.c | 15 |
3 files changed, 25 insertions, 92 deletions
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75ec3b1a..5c5ebb4db5f7 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c | |||
@@ -257,6 +257,9 @@ static const struct clk_ops dpll1_ck_ops = { | |||
257 | .get_parent = &omap2_init_dpll_parent, | 257 | .get_parent = &omap2_init_dpll_parent, |
258 | .recalc_rate = &omap3_dpll_recalc, | 258 | .recalc_rate = &omap3_dpll_recalc, |
259 | .set_rate = &omap3_noncore_dpll_set_rate, | 259 | .set_rate = &omap3_noncore_dpll_set_rate, |
260 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
261 | .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, | ||
262 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
260 | .round_rate = &omap2_dpll_round_rate, | 263 | .round_rate = &omap2_dpll_round_rate, |
261 | }; | 264 | }; |
262 | 265 | ||
@@ -367,6 +370,9 @@ static const struct clk_ops dpll4_ck_ops = { | |||
367 | .get_parent = &omap2_init_dpll_parent, | 370 | .get_parent = &omap2_init_dpll_parent, |
368 | .recalc_rate = &omap3_dpll_recalc, | 371 | .recalc_rate = &omap3_dpll_recalc, |
369 | .set_rate = &omap3_dpll4_set_rate, | 372 | .set_rate = &omap3_dpll4_set_rate, |
373 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
374 | .set_rate_and_parent = &omap3_dpll4_set_rate_and_parent, | ||
375 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
370 | .round_rate = &omap2_dpll_round_rate, | 376 | .round_rate = &omap2_dpll_round_rate, |
371 | }; | 377 | }; |
372 | 378 | ||
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index cfe7c30235d1..20e120d071dd 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
@@ -460,93 +460,6 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) | |||
460 | /* Non-CORE DPLL rate set code */ | 460 | /* Non-CORE DPLL rate set code */ |
461 | 461 | ||
462 | /** | 462 | /** |
463 | * omap3_noncore_dpll_set_rate - set non-core DPLL rate | ||
464 | * @clk: struct clk * of DPLL to set | ||
465 | * @rate: rounded target rate | ||
466 | * | ||
467 | * Set the DPLL CLKOUT to the target rate. If the DPLL can enter | ||
468 | * low-power bypass, and the target rate is the bypass source clock | ||
469 | * rate, then configure the DPLL for bypass. Otherwise, round the | ||
470 | * target rate if it hasn't been done already, then program and lock | ||
471 | * the DPLL. Returns -EINVAL upon error, or 0 upon success. | ||
472 | */ | ||
473 | int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, | ||
474 | unsigned long parent_rate) | ||
475 | { | ||
476 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | ||
477 | struct clk *new_parent = NULL; | ||
478 | unsigned long rrate; | ||
479 | u16 freqsel = 0; | ||
480 | struct dpll_data *dd; | ||
481 | int ret; | ||
482 | |||
483 | if (!hw || !rate) | ||
484 | return -EINVAL; | ||
485 | |||
486 | dd = clk->dpll_data; | ||
487 | if (!dd) | ||
488 | return -EINVAL; | ||
489 | |||
490 | if (__clk_get_rate(dd->clk_bypass) == rate && | ||
491 | (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { | ||
492 | pr_debug("%s: %s: set rate: entering bypass.\n", | ||
493 | __func__, __clk_get_name(hw->clk)); | ||
494 | |||
495 | __clk_prepare(dd->clk_bypass); | ||
496 | clk_enable(dd->clk_bypass); | ||
497 | ret = _omap3_noncore_dpll_bypass(clk); | ||
498 | if (!ret) | ||
499 | new_parent = dd->clk_bypass; | ||
500 | clk_disable(dd->clk_bypass); | ||
501 | __clk_unprepare(dd->clk_bypass); | ||
502 | } else { | ||
503 | __clk_prepare(dd->clk_ref); | ||
504 | clk_enable(dd->clk_ref); | ||
505 | |||
506 | /* XXX this check is probably pointless in the CCF context */ | ||
507 | if (dd->last_rounded_rate != rate) { | ||
508 | rrate = __clk_round_rate(hw->clk, rate); | ||
509 | if (rrate != rate) { | ||
510 | pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n", | ||
511 | __func__, __clk_get_name(hw->clk), | ||
512 | rrate, rate); | ||
513 | rate = rrate; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | if (dd->last_rounded_rate == 0) | ||
518 | return -EINVAL; | ||
519 | |||
520 | /* Freqsel is available only on OMAP343X devices */ | ||
521 | if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { | ||
522 | freqsel = _omap3_dpll_compute_freqsel(clk, | ||
523 | dd->last_rounded_n); | ||
524 | WARN_ON(!freqsel); | ||
525 | } | ||
526 | |||
527 | pr_debug("%s: %s: set rate: locking rate to %lu.\n", | ||
528 | __func__, __clk_get_name(hw->clk), rate); | ||
529 | |||
530 | ret = omap3_noncore_dpll_program(clk, freqsel); | ||
531 | if (!ret) | ||
532 | new_parent = dd->clk_ref; | ||
533 | clk_disable(dd->clk_ref); | ||
534 | __clk_unprepare(dd->clk_ref); | ||
535 | } | ||
536 | /* | ||
537 | * FIXME - this is all wrong. common code handles reparenting and | ||
538 | * migrating prepare/enable counts. dplls should be a multiplexer | ||
539 | * clock and this should be a set_parent operation so that all of that | ||
540 | * stuff is inherited for free | ||
541 | */ | ||
542 | |||
543 | if (!ret && clk_get_parent(hw->clk) != new_parent) | ||
544 | __clk_reparent(hw->clk, new_parent); | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | /** | ||
550 | * omap3_noncore_dpll_determine_rate - determine rate for a DPLL | 463 | * omap3_noncore_dpll_determine_rate - determine rate for a DPLL |
551 | * @hw: pointer to the clock to determine rate for | 464 | * @hw: pointer to the clock to determine rate for |
552 | * @rate: target rate for the DPLL | 465 | * @rate: target rate for the DPLL |
@@ -611,7 +524,7 @@ int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index) | |||
611 | } | 524 | } |
612 | 525 | ||
613 | /** | 526 | /** |
614 | * omap3_noncore_dpll_set_rate_new - set rate for a DPLL clock | 527 | * omap3_noncore_dpll_set_rate - set rate for a DPLL clock |
615 | * @hw: pointer to the clock to set parent for | 528 | * @hw: pointer to the clock to set parent for |
616 | * @rate: target rate for the clock | 529 | * @rate: target rate for the clock |
617 | * @parent_rate: rate of the parent clock | 530 | * @parent_rate: rate of the parent clock |
@@ -621,9 +534,8 @@ int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index) | |||
621 | * changed) and proceeds with the rate change operation. Returns 0 | 534 | * changed) and proceeds with the rate change operation. Returns 0 |
622 | * with success, negative error value otherwise. | 535 | * with success, negative error value otherwise. |
623 | */ | 536 | */ |
624 | static int omap3_noncore_dpll_set_rate_new(struct clk_hw *hw, | 537 | int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, |
625 | unsigned long rate, | 538 | unsigned long parent_rate) |
626 | unsigned long parent_rate) | ||
627 | { | 539 | { |
628 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | 540 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); |
629 | struct dpll_data *dd; | 541 | struct dpll_data *dd; |
@@ -688,7 +600,7 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, | |||
688 | if (index) | 600 | if (index) |
689 | ret = omap3_noncore_dpll_set_parent(hw, index); | 601 | ret = omap3_noncore_dpll_set_parent(hw, index); |
690 | else | 602 | else |
691 | ret = omap3_noncore_dpll_set_rate_new(hw, rate, parent_rate); | 603 | ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate); |
692 | 604 | ||
693 | return ret; | 605 | return ret; |
694 | } | 606 | } |
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 79791e1bf282..85ac0dd501de 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c | |||
@@ -33,6 +33,9 @@ static const struct clk_ops dpll_m4xen_ck_ops = { | |||
33 | .recalc_rate = &omap4_dpll_regm4xen_recalc, | 33 | .recalc_rate = &omap4_dpll_regm4xen_recalc, |
34 | .round_rate = &omap4_dpll_regm4xen_round_rate, | 34 | .round_rate = &omap4_dpll_regm4xen_round_rate, |
35 | .set_rate = &omap3_noncore_dpll_set_rate, | 35 | .set_rate = &omap3_noncore_dpll_set_rate, |
36 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
37 | .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, | ||
38 | .determine_rate = &omap4_dpll_regm4xen_determine_rate, | ||
36 | .get_parent = &omap2_init_dpll_parent, | 39 | .get_parent = &omap2_init_dpll_parent, |
37 | }; | 40 | }; |
38 | #else | 41 | #else |
@@ -53,6 +56,9 @@ static const struct clk_ops dpll_ck_ops = { | |||
53 | .recalc_rate = &omap3_dpll_recalc, | 56 | .recalc_rate = &omap3_dpll_recalc, |
54 | .round_rate = &omap2_dpll_round_rate, | 57 | .round_rate = &omap2_dpll_round_rate, |
55 | .set_rate = &omap3_noncore_dpll_set_rate, | 58 | .set_rate = &omap3_noncore_dpll_set_rate, |
59 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
60 | .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, | ||
61 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
56 | .get_parent = &omap2_init_dpll_parent, | 62 | .get_parent = &omap2_init_dpll_parent, |
57 | }; | 63 | }; |
58 | 64 | ||
@@ -61,6 +67,9 @@ static const struct clk_ops dpll_no_gate_ck_ops = { | |||
61 | .get_parent = &omap2_init_dpll_parent, | 67 | .get_parent = &omap2_init_dpll_parent, |
62 | .round_rate = &omap2_dpll_round_rate, | 68 | .round_rate = &omap2_dpll_round_rate, |
63 | .set_rate = &omap3_noncore_dpll_set_rate, | 69 | .set_rate = &omap3_noncore_dpll_set_rate, |
70 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
71 | .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, | ||
72 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
64 | }; | 73 | }; |
65 | #else | 74 | #else |
66 | static const struct clk_ops dpll_core_ck_ops = {}; | 75 | static const struct clk_ops dpll_core_ck_ops = {}; |
@@ -97,6 +106,9 @@ static const struct clk_ops omap3_dpll_ck_ops = { | |||
97 | .get_parent = &omap2_init_dpll_parent, | 106 | .get_parent = &omap2_init_dpll_parent, |
98 | .recalc_rate = &omap3_dpll_recalc, | 107 | .recalc_rate = &omap3_dpll_recalc, |
99 | .set_rate = &omap3_noncore_dpll_set_rate, | 108 | .set_rate = &omap3_noncore_dpll_set_rate, |
109 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
110 | .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, | ||
111 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
100 | .round_rate = &omap2_dpll_round_rate, | 112 | .round_rate = &omap2_dpll_round_rate, |
101 | }; | 113 | }; |
102 | 114 | ||
@@ -106,6 +118,9 @@ static const struct clk_ops omap3_dpll_per_ck_ops = { | |||
106 | .get_parent = &omap2_init_dpll_parent, | 118 | .get_parent = &omap2_init_dpll_parent, |
107 | .recalc_rate = &omap3_dpll_recalc, | 119 | .recalc_rate = &omap3_dpll_recalc, |
108 | .set_rate = &omap3_dpll4_set_rate, | 120 | .set_rate = &omap3_dpll4_set_rate, |
121 | .set_parent = &omap3_noncore_dpll_set_parent, | ||
122 | .set_rate_and_parent = &omap3_dpll4_set_rate_and_parent, | ||
123 | .determine_rate = &omap3_noncore_dpll_determine_rate, | ||
109 | .round_rate = &omap2_dpll_round_rate, | 124 | .round_rate = &omap2_dpll_round_rate, |
110 | }; | 125 | }; |
111 | #endif | 126 | #endif |