diff options
author | Richard Woodruff <r-woodruff2@ti.com> | 2010-02-23 00:09:08 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-02-24 14:15:02 -0500 |
commit | 358965d7bab9c70c11b64931da02667b161cb03a (patch) | |
tree | 884a13c783f9ba43cc5fe063c5fbeecde7804f58 /arch/arm/mach-omap2/dpll3xxx.c | |
parent | 91808a81fe7cc8a786b575ebc2d102c59d83c1a7 (diff) |
OMAP3 clock: introduce DPLL4 Jtype
DPLL4 for 3630 introduces a changed block called j type dpll, requiring
special divisor bits and additional reg fields. To allow for silicons to
use this, this is introduced as a flag and is enabled for 3630 silicon.
OMAP4 also has j type dpll for usb.
Tested with 3630 ZOOM3 and OMAP3430 ZOOM2
Signed-off-by: Richard Woodruff <r-woodruff2@ti.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Vishwanath BS <Vishwanath.bs@ti.com>
[paul@pwsan.com: added some comments; updated copyrights and credits; fixed
some style issues]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/dpll3xxx.c')
-rw-r--r-- | arch/arm/mach-omap2/dpll3xxx.c | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 68268cd89e05..417c3caa05db 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
@@ -1,11 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * OMAP3/4 - specific DPLL control functions | 2 | * OMAP3/4 - specific DPLL control functions |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Texas Instruments, Inc. | 4 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
5 | * Copyright (C) 2009 Nokia Corporation | 5 | * Copyright (C) 2009-2010 Nokia Corporation |
6 | * | 6 | * |
7 | * Written by Paul Walmsley | 7 | * Written by Paul Walmsley |
8 | * Testing and integration fixes by Jouni Högander | 8 | * Testing and integration fixes by Jouni Högander |
9 | * | ||
10 | * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth | ||
11 | * Menon | ||
9 | * | 12 | * |
10 | * Parts of this code are based on code written by | 13 | * Parts of this code are based on code written by |
11 | * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu | 14 | * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu |
@@ -225,6 +228,47 @@ static int _omap3_noncore_dpll_stop(struct clk *clk) | |||
225 | return 0; | 228 | return 0; |
226 | } | 229 | } |
227 | 230 | ||
231 | /** | ||
232 | * lookup_dco_sddiv - Set j-type DPLL4 compensation variables | ||
233 | * @clk: pointer to a DPLL struct clk | ||
234 | * @dco: digital control oscillator selector | ||
235 | * @sd_div: target sigma-delta divider | ||
236 | * @m: DPLL multiplier to set | ||
237 | * @n: DPLL divider to set | ||
238 | * | ||
239 | * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)" | ||
240 | * | ||
241 | * XXX This code is not needed for 3430/AM35xx; can it be optimized | ||
242 | * out in non-multi-OMAP builds for those chips? | ||
243 | */ | ||
244 | static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m, | ||
245 | u8 n) | ||
246 | { | ||
247 | unsigned long fint, clkinp, sd; /* watch out for overflow */ | ||
248 | int mod1, mod2; | ||
249 | |||
250 | clkinp = clk->parent->rate; | ||
251 | fint = (clkinp / n) * m; | ||
252 | |||
253 | if (fint < 1000000000) | ||
254 | *dco = 2; | ||
255 | else | ||
256 | *dco = 4; | ||
257 | /* | ||
258 | * target sigma-delta to near 250MHz | ||
259 | * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)] | ||
260 | */ | ||
261 | clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */ | ||
262 | mod1 = (clkinp * m) % (250 * n); | ||
263 | sd = (clkinp * m) / (250 * n); | ||
264 | mod2 = sd % 10; | ||
265 | sd /= 10; | ||
266 | |||
267 | if (mod1 || mod2) | ||
268 | sd++; | ||
269 | *sd_div = sd; | ||
270 | } | ||
271 | |||
228 | /* | 272 | /* |
229 | * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly | 273 | * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly |
230 | * @clk: struct clk * of DPLL to set | 274 | * @clk: struct clk * of DPLL to set |
@@ -259,6 +303,21 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) | |||
259 | v &= ~(dd->mult_mask | dd->div1_mask); | 303 | v &= ~(dd->mult_mask | dd->div1_mask); |
260 | v |= m << __ffs(dd->mult_mask); | 304 | v |= m << __ffs(dd->mult_mask); |
261 | v |= (n - 1) << __ffs(dd->div1_mask); | 305 | v |= (n - 1) << __ffs(dd->div1_mask); |
306 | |||
307 | /* | ||
308 | * XXX This code is not needed for 3430/AM35XX; can it be optimized | ||
309 | * out in non-multi-OMAP builds for those chips? | ||
310 | */ | ||
311 | if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) { | ||
312 | u8 dco, sd_div; | ||
313 | lookup_dco_sddiv(clk, &dco, &sd_div, m, n); | ||
314 | /* XXX This probably will need revision for OMAP4 */ | ||
315 | v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK | ||
316 | | OMAP3630_PERIPH_DPLL_SD_DIV_MASK); | ||
317 | v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK); | ||
318 | v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK); | ||
319 | } | ||
320 | |||
262 | __raw_writel(v, dd->mult_div1_reg); | 321 | __raw_writel(v, dd->mult_div1_reg); |
263 | 322 | ||
264 | /* We let the clock framework set the other output dividers later */ | 323 | /* We let the clock framework set the other output dividers later */ |
@@ -536,7 +595,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk) | |||
536 | 595 | ||
537 | v = __raw_readl(dd->control_reg) & dd->enable_mask; | 596 | v = __raw_readl(dd->control_reg) & dd->enable_mask; |
538 | v >>= __ffs(dd->enable_mask); | 597 | v >>= __ffs(dd->enable_mask); |
539 | if (v != OMAP3XXX_EN_DPLL_LOCKED) | 598 | if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) |
540 | rate = clk->parent->rate; | 599 | rate = clk->parent->rate; |
541 | else | 600 | else |
542 | rate = clk->parent->rate * 2; | 601 | rate = clk->parent->rate * 2; |