aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2014-10-03 09:57:14 -0400
committerPaul Walmsley <paul@pwsan.com>2014-11-13 11:26:45 -0500
commit2e1a7b014f9c3d61fbf12b429f0479242264dbec (patch)
treececb7c3739740f991c03eda4f0fbfd075458cd82
parente3ab6013ab06d3a861ed00c1f8d32aa4e6b66ddd (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.c6
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c96
-rw-r--r--drivers/clk/ti/dpll.c15
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 */
473int 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 */
624static int omap3_noncore_dpll_set_rate_new(struct clk_hw *hw, 537int 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
66static const struct clk_ops dpll_core_ck_ops = {}; 75static 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