aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/dpll3xxx.c
diff options
context:
space:
mode:
authorRichard Woodruff <r-woodruff2@ti.com>2010-02-23 00:09:08 -0500
committerPaul Walmsley <paul@pwsan.com>2010-02-24 14:15:02 -0500
commit358965d7bab9c70c11b64931da02667b161cb03a (patch)
tree884a13c783f9ba43cc5fe063c5fbeecde7804f58 /arch/arm/mach-omap2/dpll3xxx.c
parent91808a81fe7cc8a786b575ebc2d102c59d83c1a7 (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.c67
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 */
244static 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;