diff options
Diffstat (limited to 'arch/arm/mach-omap2/clock.c')
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 76e20bcc4e8a..752e34787f21 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -58,12 +58,68 @@ | |||
58 | #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ | 58 | #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ |
59 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) | 59 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) |
60 | 60 | ||
61 | /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ | ||
62 | #define DPLL_FINT_BAND1_MIN 750000 | ||
63 | #define DPLL_FINT_BAND1_MAX 2100000 | ||
64 | #define DPLL_FINT_BAND2_MIN 7500000 | ||
65 | #define DPLL_FINT_BAND2_MAX 21000000 | ||
66 | |||
67 | /* _dpll_test_fint() return codes */ | ||
68 | #define DPLL_FINT_UNDERFLOW -1 | ||
69 | #define DPLL_FINT_INVALID -2 | ||
70 | |||
61 | u8 cpu_mask; | 71 | u8 cpu_mask; |
62 | 72 | ||
63 | /*------------------------------------------------------------------------- | 73 | /*------------------------------------------------------------------------- |
64 | * OMAP2/3 specific clock functions | 74 | * OMAP2/3 specific clock functions |
65 | *-------------------------------------------------------------------------*/ | 75 | *-------------------------------------------------------------------------*/ |
66 | 76 | ||
77 | /* | ||
78 | * _dpll_test_fint - test whether an Fint value is valid for the DPLL | ||
79 | * @clk: DPLL struct clk to test | ||
80 | * @n: divider value (N) to test | ||
81 | * | ||
82 | * Tests whether a particular divider @n will result in a valid DPLL | ||
83 | * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter | ||
84 | * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate | ||
85 | * (assuming that it is counting N upwards), or -2 if the enclosing loop | ||
86 | * should skip to the next iteration (again assuming N is increasing). | ||
87 | */ | ||
88 | static int _dpll_test_fint(struct clk *clk, u8 n) | ||
89 | { | ||
90 | struct dpll_data *dd; | ||
91 | long fint; | ||
92 | int ret = 0; | ||
93 | |||
94 | dd = clk->dpll_data; | ||
95 | |||
96 | /* DPLL divider must result in a valid jitter correction val */ | ||
97 | fint = clk->parent->rate / (n + 1); | ||
98 | if (fint < DPLL_FINT_BAND1_MIN) { | ||
99 | |||
100 | pr_debug("rejecting n=%d due to Fint failure, " | ||
101 | "lowering max_divider\n", n); | ||
102 | dd->max_divider = n; | ||
103 | ret = DPLL_FINT_UNDERFLOW; | ||
104 | |||
105 | } else if (fint > DPLL_FINT_BAND1_MAX && | ||
106 | fint < DPLL_FINT_BAND2_MIN) { | ||
107 | |||
108 | pr_debug("rejecting n=%d due to Fint failure\n", n); | ||
109 | ret = DPLL_FINT_INVALID; | ||
110 | |||
111 | } else if (fint > DPLL_FINT_BAND2_MAX) { | ||
112 | |||
113 | pr_debug("rejecting n=%d due to Fint failure, " | ||
114 | "boosting min_divider\n", n); | ||
115 | dd->min_divider = n; | ||
116 | ret = DPLL_FINT_INVALID; | ||
117 | |||
118 | } | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
67 | /** | 123 | /** |
68 | * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk | 124 | * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk |
69 | * @clk: OMAP clock struct ptr to use | 125 | * @clk: OMAP clock struct ptr to use |
@@ -892,7 +948,14 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
892 | 948 | ||
893 | dd->last_rounded_rate = 0; | 949 | dd->last_rounded_rate = 0; |
894 | 950 | ||
895 | for (n = DPLL_MIN_DIVIDER; n <= dd->max_divider; n++) { | 951 | for (n = dd->min_divider; n <= dd->max_divider; n++) { |
952 | |||
953 | /* Is the (input clk, divider) pair valid for the DPLL? */ | ||
954 | r = _dpll_test_fint(clk, n); | ||
955 | if (r == DPLL_FINT_UNDERFLOW) | ||
956 | break; | ||
957 | else if (r == DPLL_FINT_INVALID) | ||
958 | continue; | ||
896 | 959 | ||
897 | /* Compute the scaled DPLL multiplier, based on the divider */ | 960 | /* Compute the scaled DPLL multiplier, based on the divider */ |
898 | m = scaled_rt_rp * n; | 961 | m = scaled_rt_rp * n; |
@@ -926,7 +989,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
926 | pr_debug("clock: found new least error %d\n", min_e); | 989 | pr_debug("clock: found new least error %d\n", min_e); |
927 | 990 | ||
928 | /* We found good settings -- bail out now */ | 991 | /* We found good settings -- bail out now */ |
929 | if (min_e <= clk->dpll_data->rate_tolerance) | 992 | if (min_e <= dd->rate_tolerance) |
930 | break; | 993 | break; |
931 | } | 994 | } |
932 | } | 995 | } |