aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/dpll3xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/dpll3xxx.c')
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c82
1 files changed, 70 insertions, 12 deletions
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 2b559fc64855..b32ccd954a1b 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
@@ -15,7 +18,6 @@
15 * published by the Free Software Foundation. 18 * published by the Free Software Foundation.
16 */ 19 */
17 20
18#include <linux/module.h>
19#include <linux/kernel.h> 21#include <linux/kernel.h>
20#include <linux/device.h> 22#include <linux/device.h>
21#include <linux/list.h> 23#include <linux/list.h>
@@ -23,13 +25,10 @@
23#include <linux/delay.h> 25#include <linux/delay.h>
24#include <linux/clk.h> 26#include <linux/clk.h>
25#include <linux/io.h> 27#include <linux/io.h>
26#include <linux/limits.h>
27#include <linux/bitops.h> 28#include <linux/bitops.h>
28 29
29#include <plat/cpu.h> 30#include <plat/cpu.h>
30#include <plat/clock.h> 31#include <plat/clock.h>
31#include <plat/sram.h>
32#include <asm/div64.h>
33#include <asm/clkdev.h> 32#include <asm/clkdev.h>
34 33
35#include "clock.h" 34#include "clock.h"
@@ -225,6 +224,47 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
225 return 0; 224 return 0;
226} 225}
227 226
227/**
228 * lookup_dco_sddiv - Set j-type DPLL4 compensation variables
229 * @clk: pointer to a DPLL struct clk
230 * @dco: digital control oscillator selector
231 * @sd_div: target sigma-delta divider
232 * @m: DPLL multiplier to set
233 * @n: DPLL divider to set
234 *
235 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
236 *
237 * XXX This code is not needed for 3430/AM35xx; can it be optimized
238 * out in non-multi-OMAP builds for those chips?
239 */
240static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
241 u8 n)
242{
243 unsigned long fint, clkinp, sd; /* watch out for overflow */
244 int mod1, mod2;
245
246 clkinp = clk->parent->rate;
247 fint = (clkinp / n) * m;
248
249 if (fint < 1000000000)
250 *dco = 2;
251 else
252 *dco = 4;
253 /*
254 * target sigma-delta to near 250MHz
255 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
256 */
257 clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
258 mod1 = (clkinp * m) % (250 * n);
259 sd = (clkinp * m) / (250 * n);
260 mod2 = sd % 10;
261 sd /= 10;
262
263 if (mod1 || mod2)
264 sd++;
265 *sd_div = sd;
266}
267
228/* 268/*
229 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly 269 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
230 * @clk: struct clk * of DPLL to set 270 * @clk: struct clk * of DPLL to set
@@ -243,8 +283,11 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
243 /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ 283 /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
244 _omap3_noncore_dpll_bypass(clk); 284 _omap3_noncore_dpll_bypass(clk);
245 285
246 /* Set jitter correction */ 286 /*
247 if (!cpu_is_omap44xx()) { 287 * Set jitter correction. No jitter correction for OMAP4 and 3630
288 * since freqsel field is no longer present
289 */
290 if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
248 v = __raw_readl(dd->control_reg); 291 v = __raw_readl(dd->control_reg);
249 v &= ~dd->freqsel_mask; 292 v &= ~dd->freqsel_mask;
250 v |= freqsel << __ffs(dd->freqsel_mask); 293 v |= freqsel << __ffs(dd->freqsel_mask);
@@ -256,6 +299,21 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
256 v &= ~(dd->mult_mask | dd->div1_mask); 299 v &= ~(dd->mult_mask | dd->div1_mask);
257 v |= m << __ffs(dd->mult_mask); 300 v |= m << __ffs(dd->mult_mask);
258 v |= (n - 1) << __ffs(dd->div1_mask); 301 v |= (n - 1) << __ffs(dd->div1_mask);
302
303 /*
304 * XXX This code is not needed for 3430/AM35XX; can it be optimized
305 * out in non-multi-OMAP builds for those chips?
306 */
307 if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) {
308 u8 dco, sd_div;
309 lookup_dco_sddiv(clk, &dco, &sd_div, m, n);
310 /* XXX This probably will need revision for OMAP4 */
311 v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK
312 | OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
313 v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK);
314 v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
315 }
316
259 __raw_writel(v, dd->mult_div1_reg); 317 __raw_writel(v, dd->mult_div1_reg);
260 318
261 /* We let the clock framework set the other output dividers later */ 319 /* We let the clock framework set the other output dividers later */
@@ -387,8 +445,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
387 if (dd->last_rounded_rate == 0) 445 if (dd->last_rounded_rate == 0)
388 return -EINVAL; 446 return -EINVAL;
389 447
390 /* No freqsel on OMAP4 */ 448 /* No freqsel on OMAP4 and OMAP3630 */
391 if (!cpu_is_omap44xx()) { 449 if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
392 freqsel = _omap3_dpll_compute_freqsel(clk, 450 freqsel = _omap3_dpll_compute_freqsel(clk,
393 dd->last_rounded_n); 451 dd->last_rounded_n);
394 if (!freqsel) 452 if (!freqsel)
@@ -533,7 +591,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
533 591
534 v = __raw_readl(dd->control_reg) & dd->enable_mask; 592 v = __raw_readl(dd->control_reg) & dd->enable_mask;
535 v >>= __ffs(dd->enable_mask); 593 v >>= __ffs(dd->enable_mask);
536 if (v != OMAP3XXX_EN_DPLL_LOCKED) 594 if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
537 rate = clk->parent->rate; 595 rate = clk->parent->rate;
538 else 596 else
539 rate = clk->parent->rate * 2; 597 rate = clk->parent->rate * 2;