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 | |
| 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>
| -rw-r--r-- | arch/arm/mach-omap2/clock.h | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clock34xx_data.c | 32 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clock44xx_data.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/cm-regbits-34xx.h | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/dpll3xxx.c | 67 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/clock.h | 5 |
6 files changed, 109 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 86e32bf2a693..0b0f52083121 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
| @@ -47,6 +47,10 @@ | |||
| 47 | #define DPLL_LOW_POWER_BYPASS 0x5 | 47 | #define DPLL_LOW_POWER_BYPASS 0x5 |
| 48 | #define DPLL_LOCKED 0x7 | 48 | #define DPLL_LOCKED 0x7 |
| 49 | 49 | ||
| 50 | /* DPLL Type and DCO Selection Flags */ | ||
| 51 | #define DPLL_J_TYPE 0x1 | ||
| 52 | #define DPLL_NO_DCO_SEL 0x2 | ||
| 53 | |||
| 50 | int omap2_clk_enable(struct clk *clk); | 54 | int omap2_clk_enable(struct clk *clk); |
| 51 | void omap2_clk_disable(struct clk *clk); | 55 | void omap2_clk_disable(struct clk *clk); |
| 52 | long omap2_clk_round_rate(struct clk *clk, unsigned long rate); | 56 | long omap2_clk_round_rate(struct clk *clk, unsigned long rate); |
diff --git a/arch/arm/mach-omap2/clock34xx_data.c b/arch/arm/mach-omap2/clock34xx_data.c index 8bb8134872ce..60c6140b86af 100644 --- a/arch/arm/mach-omap2/clock34xx_data.c +++ b/arch/arm/mach-omap2/clock34xx_data.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | /* Maximum DPLL multiplier, divider values for OMAP3 */ | 39 | /* Maximum DPLL multiplier, divider values for OMAP3 */ |
| 40 | #define OMAP3_MAX_DPLL_MULT 2048 | 40 | #define OMAP3_MAX_DPLL_MULT 2048 |
| 41 | #define OMAP3630_MAX_JTYPE_DPLL_MULT 4095 | ||
| 41 | #define OMAP3_MAX_DPLL_DIV 128 | 42 | #define OMAP3_MAX_DPLL_DIV 128 |
| 42 | 43 | ||
| 43 | /* | 44 | /* |
| @@ -529,7 +530,8 @@ static struct clk emu_core_alwon_ck = { | |||
| 529 | /* DPLL4 */ | 530 | /* DPLL4 */ |
| 530 | /* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ | 531 | /* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ |
| 531 | /* Type: DPLL */ | 532 | /* Type: DPLL */ |
| 532 | static struct dpll_data dpll4_dd = { | 533 | static struct dpll_data dpll4_dd; |
| 534 | static struct dpll_data dpll4_dd_34xx __initdata = { | ||
| 533 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), | 535 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), |
| 534 | .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, | 536 | .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, |
| 535 | .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, | 537 | .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, |
| @@ -552,6 +554,29 @@ static struct dpll_data dpll4_dd = { | |||
| 552 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 554 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
| 553 | }; | 555 | }; |
| 554 | 556 | ||
| 557 | static struct dpll_data dpll4_dd_3630 __initdata = { | ||
| 558 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), | ||
| 559 | .mult_mask = OMAP3630_PERIPH_DPLL_MULT_MASK, | ||
| 560 | .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, | ||
| 561 | .clk_bypass = &sys_ck, | ||
| 562 | .clk_ref = &sys_ck, | ||
| 563 | .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), | ||
| 564 | .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK, | ||
| 565 | .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), | ||
| 566 | .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT, | ||
| 567 | .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT, | ||
| 568 | .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT, | ||
| 569 | .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), | ||
| 570 | .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, | ||
| 571 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), | ||
| 572 | .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, | ||
| 573 | .max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT, | ||
| 574 | .min_divider = 1, | ||
| 575 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
| 576 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE, | ||
| 577 | .flags = DPLL_J_TYPE | ||
| 578 | }; | ||
| 579 | |||
| 555 | static struct clk dpll4_ck = { | 580 | static struct clk dpll4_ck = { |
| 556 | .name = "dpll4_ck", | 581 | .name = "dpll4_ck", |
| 557 | .ops = &omap3_clkops_noncore_dpll_ops, | 582 | .ops = &omap3_clkops_noncore_dpll_ops, |
| @@ -3377,6 +3402,11 @@ int __init omap3xxx_clk_init(void) | |||
| 3377 | &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore; | 3402 | &clkops_omap36xx_pwrdn_with_hsdiv_wait_restore; |
| 3378 | } | 3403 | } |
| 3379 | 3404 | ||
| 3405 | if (cpu_is_omap3630()) | ||
| 3406 | dpll4_dd = dpll4_dd_3630; | ||
| 3407 | else | ||
| 3408 | dpll4_dd = dpll4_dd_34xx; | ||
| 3409 | |||
| 3380 | clk_init(&omap2_clk_functions); | 3410 | clk_init(&omap2_clk_functions); |
| 3381 | 3411 | ||
| 3382 | for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++) | 3412 | for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++) |
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 86af31d80a34..8d8b57340950 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c | |||
| @@ -980,6 +980,7 @@ static struct dpll_data dpll_usb_dd = { | |||
| 980 | .max_multiplier = OMAP4430_MAX_DPLL_MULT, | 980 | .max_multiplier = OMAP4430_MAX_DPLL_MULT, |
| 981 | .max_divider = OMAP4430_MAX_DPLL_DIV, | 981 | .max_divider = OMAP4430_MAX_DPLL_DIV, |
| 982 | .min_divider = 1, | 982 | .min_divider = 1, |
| 983 | .flags = DPLL_J_TYPE | DPLL_NO_DCO_SEL | ||
| 983 | }; | 984 | }; |
| 984 | 985 | ||
| 985 | 986 | ||
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index c04c7c68f033..29cd13b838ca 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h | |||
| @@ -531,8 +531,13 @@ | |||
| 531 | /* CM_CLKSEL2_PLL */ | 531 | /* CM_CLKSEL2_PLL */ |
| 532 | #define OMAP3430_PERIPH_DPLL_MULT_SHIFT 8 | 532 | #define OMAP3430_PERIPH_DPLL_MULT_SHIFT 8 |
| 533 | #define OMAP3430_PERIPH_DPLL_MULT_MASK (0x7ff << 8) | 533 | #define OMAP3430_PERIPH_DPLL_MULT_MASK (0x7ff << 8) |
| 534 | #define OMAP3630_PERIPH_DPLL_MULT_MASK (0xfff << 8) | ||
| 534 | #define OMAP3430_PERIPH_DPLL_DIV_SHIFT 0 | 535 | #define OMAP3430_PERIPH_DPLL_DIV_SHIFT 0 |
| 535 | #define OMAP3430_PERIPH_DPLL_DIV_MASK (0x7f << 0) | 536 | #define OMAP3430_PERIPH_DPLL_DIV_MASK (0x7f << 0) |
| 537 | #define OMAP3630_PERIPH_DPLL_DCO_SEL_SHIFT 21 | ||
| 538 | #define OMAP3630_PERIPH_DPLL_DCO_SEL_MASK (0x7 << 21) | ||
| 539 | #define OMAP3630_PERIPH_DPLL_SD_DIV_SHIFT 24 | ||
| 540 | #define OMAP3630_PERIPH_DPLL_SD_DIV_MASK (0xff << 24) | ||
| 536 | 541 | ||
| 537 | /* CM_CLKSEL3_PLL */ | 542 | /* CM_CLKSEL3_PLL */ |
| 538 | #define OMAP3430_DIV_96M_SHIFT 0 | 543 | #define OMAP3430_DIV_96M_SHIFT 0 |
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; |
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index e49162469791..f5f30c73db33 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h | |||
| @@ -41,6 +41,10 @@ struct clksel { | |||
| 41 | const struct clksel_rate *rates; | 41 | const struct clksel_rate *rates; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | /* | ||
| 45 | * A new flag called flag has been added which indicates what is the | ||
| 46 | * type of dpll (like j_type, no_dco_sel) | ||
| 47 | */ | ||
| 44 | struct dpll_data { | 48 | struct dpll_data { |
| 45 | void __iomem *mult_div1_reg; | 49 | void __iomem *mult_div1_reg; |
| 46 | u32 mult_mask; | 50 | u32 mult_mask; |
| @@ -67,6 +71,7 @@ struct dpll_data { | |||
| 67 | u8 auto_recal_bit; | 71 | u8 auto_recal_bit; |
| 68 | u8 recal_en_bit; | 72 | u8 recal_en_bit; |
| 69 | u8 recal_st_bit; | 73 | u8 recal_st_bit; |
| 74 | u8 flags; | ||
| 70 | # endif | 75 | # endif |
| 71 | }; | 76 | }; |
| 72 | 77 | ||
