diff options
Diffstat (limited to 'arch/arm/mach-omap2/clock.c')
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 5020cb1f2e7e..40cb65ba1fac 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -211,25 +211,52 @@ void omap2_init_clksel_parent(struct clk *clk) | |||
211 | return; | 211 | return; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* Returns the DPLL rate */ | 214 | /** |
215 | * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate | ||
216 | * @clk: struct clk * of a DPLL | ||
217 | * | ||
218 | * DPLLs can be locked or bypassed - basically, enabled or disabled. | ||
219 | * When locked, the DPLL output depends on the M and N values. When | ||
220 | * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock | ||
221 | * or sys_clk. Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and | ||
222 | * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively | ||
223 | * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk. | ||
224 | * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is | ||
225 | * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0 | ||
226 | * if the clock @clk is not a DPLL. | ||
227 | */ | ||
215 | u32 omap2_get_dpll_rate(struct clk *clk) | 228 | u32 omap2_get_dpll_rate(struct clk *clk) |
216 | { | 229 | { |
217 | long long dpll_clk; | 230 | long long dpll_clk; |
218 | u32 dpll_mult, dpll_div, dpll; | 231 | u32 dpll_mult, dpll_div, v; |
219 | struct dpll_data *dd; | 232 | struct dpll_data *dd; |
220 | 233 | ||
221 | dd = clk->dpll_data; | 234 | dd = clk->dpll_data; |
222 | /* REVISIT: What do we return on error? */ | ||
223 | if (!dd) | 235 | if (!dd) |
224 | return 0; | 236 | return 0; |
225 | 237 | ||
226 | dpll = __raw_readl(dd->mult_div1_reg); | 238 | /* Return bypass rate if DPLL is bypassed */ |
227 | dpll_mult = dpll & dd->mult_mask; | 239 | v = __raw_readl(dd->control_reg); |
240 | v &= dd->enable_mask; | ||
241 | v >>= __ffs(dd->enable_mask); | ||
242 | |||
243 | if (cpu_is_omap24xx()) { | ||
244 | if (v == OMAP2XXX_EN_DPLL_LPBYPASS || | ||
245 | v == OMAP2XXX_EN_DPLL_FRBYPASS) | ||
246 | return dd->clk_bypass->rate; | ||
247 | } else if (cpu_is_omap34xx()) { | ||
248 | if (v == OMAP3XXX_EN_DPLL_LPBYPASS || | ||
249 | v == OMAP3XXX_EN_DPLL_FRBYPASS) | ||
250 | return dd->clk_bypass->rate; | ||
251 | } | ||
252 | |||
253 | v = __raw_readl(dd->mult_div1_reg); | ||
254 | dpll_mult = v & dd->mult_mask; | ||
228 | dpll_mult >>= __ffs(dd->mult_mask); | 255 | dpll_mult >>= __ffs(dd->mult_mask); |
229 | dpll_div = dpll & dd->div1_mask; | 256 | dpll_div = v & dd->div1_mask; |
230 | dpll_div >>= __ffs(dd->div1_mask); | 257 | dpll_div >>= __ffs(dd->div1_mask); |
231 | 258 | ||
232 | dpll_clk = (long long)clk->parent->rate * dpll_mult; | 259 | dpll_clk = (long long)dd->clk_ref->rate * dpll_mult; |
233 | do_div(dpll_clk, dpll_div + 1); | 260 | do_div(dpll_clk, dpll_div + 1); |
234 | 261 | ||
235 | return dpll_clk; | 262 | return dpll_clk; |
@@ -930,7 +957,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
930 | pr_debug("clock: starting DPLL round_rate for clock %s, target rate " | 957 | pr_debug("clock: starting DPLL round_rate for clock %s, target rate " |
931 | "%ld\n", clk->name, target_rate); | 958 | "%ld\n", clk->name, target_rate); |
932 | 959 | ||
933 | scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR); | 960 | scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR); |
934 | scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; | 961 | scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; |
935 | 962 | ||
936 | dd->last_rounded_rate = 0; | 963 | dd->last_rounded_rate = 0; |
@@ -957,7 +984,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
957 | break; | 984 | break; |
958 | 985 | ||
959 | r = _dpll_test_mult(&m, n, &new_rate, target_rate, | 986 | r = _dpll_test_mult(&m, n, &new_rate, target_rate, |
960 | clk->parent->rate); | 987 | dd->clk_ref->rate); |
961 | 988 | ||
962 | /* m can't be set low enough for this n - try with a larger n */ | 989 | /* m can't be set low enough for this n - try with a larger n */ |
963 | if (r == DPLL_MULT_UNDERFLOW) | 990 | if (r == DPLL_MULT_UNDERFLOW) |
@@ -988,7 +1015,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
988 | 1015 | ||
989 | dd->last_rounded_m = min_e_m; | 1016 | dd->last_rounded_m = min_e_m; |
990 | dd->last_rounded_n = min_e_n; | 1017 | dd->last_rounded_n = min_e_n; |
991 | dd->last_rounded_rate = _dpll_compute_new_rate(clk->parent->rate, | 1018 | dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate, |
992 | min_e_m, min_e_n); | 1019 | min_e_m, min_e_n); |
993 | 1020 | ||
994 | pr_debug("clock: final least error: e = %d, m = %d, n = %d\n", | 1021 | pr_debug("clock: final least error: e = %d, m = %d, n = %d\n", |