aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clock34xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/clock34xx.c')
-rw-r--r--arch/arm/mach-omap2/clock34xx.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index ba05aa42bd8e..045da923e75b 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -129,6 +129,9 @@ static struct omap_clk omap34xx_clks[] = {
129 CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), 129 CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2),
130 CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), 130 CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2),
131 CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), 131 CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
132 CLK(NULL, "modem_fck", &modem_fck, CK_343X),
133 CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X),
134 CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X),
132 CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), 135 CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X),
133 CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), 136 CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X),
134 CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), 137 CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2),
@@ -281,6 +284,22 @@ static struct omap_clk omap34xx_clks[] = {
281 284
282#define MAX_DPLL_WAIT_TRIES 1000000 285#define MAX_DPLL_WAIT_TRIES 1000000
283 286
287#define MIN_SDRC_DLL_LOCK_FREQ 83000000
288
289#define CYCLES_PER_MHZ 1000000
290
291/* Scale factor for fixed-point arith in omap3_core_dpll_m2_set_rate() */
292#define SDRC_MPURATE_SCALE 8
293
294/* 2^SDRC_MPURATE_BASE_SHIFT: MPU MHz that SDRC_MPURATE_LOOPS is defined for */
295#define SDRC_MPURATE_BASE_SHIFT 9
296
297/*
298 * SDRC_MPURATE_LOOPS: Number of MPU loops to execute at
299 * 2^MPURATE_BASE_SHIFT MHz for SDRC to stabilize
300 */
301#define SDRC_MPURATE_LOOPS 96
302
284/** 303/**
285 * omap3_dpll_recalc - recalculate DPLL rate 304 * omap3_dpll_recalc - recalculate DPLL rate
286 * @clk: DPLL struct clk 305 * @clk: DPLL struct clk
@@ -703,7 +722,9 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
703static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) 722static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
704{ 723{
705 u32 new_div = 0; 724 u32 new_div = 0;
706 unsigned long validrate, sdrcrate; 725 u32 unlock_dll = 0;
726 u32 c;
727 unsigned long validrate, sdrcrate, mpurate;
707 struct omap_sdrc_params *sp; 728 struct omap_sdrc_params *sp;
708 729
709 if (!clk || !rate) 730 if (!clk || !rate)
@@ -712,34 +733,44 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
712 if (clk != &dpll3_m2_ck) 733 if (clk != &dpll3_m2_ck)
713 return -EINVAL; 734 return -EINVAL;
714 735
715 if (rate == clk->rate)
716 return 0;
717
718 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); 736 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
719 if (validrate != rate) 737 if (validrate != rate)
720 return -EINVAL; 738 return -EINVAL;
721 739
722 sdrcrate = sdrc_ick.rate; 740 sdrcrate = sdrc_ick.rate;
723 if (rate > clk->rate) 741 if (rate > clk->rate)
724 sdrcrate <<= ((rate / clk->rate) - 1); 742 sdrcrate <<= ((rate / clk->rate) >> 1);
725 else 743 else
726 sdrcrate >>= ((clk->rate / rate) - 1); 744 sdrcrate >>= ((clk->rate / rate) >> 1);
727 745
728 sp = omap2_sdrc_get_params(sdrcrate); 746 sp = omap2_sdrc_get_params(sdrcrate);
729 if (!sp) 747 if (!sp)
730 return -EINVAL; 748 return -EINVAL;
731 749
732 pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, 750 if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
733 validrate); 751 pr_debug("clock: will unlock SDRC DLL\n");
734 pr_info("clock: SDRC timing params used: %08x %08x %08x\n", 752 unlock_dll = 1;
735 sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb); 753 }
736 754
737 /* REVISIT: SRAM code doesn't support other M2 divisors yet */ 755 /*
738 WARN_ON(new_div != 1 && new_div != 2); 756 * XXX This only needs to be done when the CPU frequency changes
757 */
758 mpurate = arm_fck.rate / CYCLES_PER_MHZ;
759 c = (mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
760 c += 1; /* for safety */
761 c *= SDRC_MPURATE_LOOPS;
762 c >>= SDRC_MPURATE_SCALE;
763 if (c == 0)
764 c = 1;
765
766 pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
767 validrate);
768 pr_debug("clock: SDRC timing params used: %08x %08x %08x\n",
769 sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
739 770
740 /* REVISIT: Add SDRC_MR changing to this code also */
741 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, 771 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
742 sp->actim_ctrlb, new_div); 772 sp->actim_ctrlb, new_div, unlock_dll, c,
773 sp->mr, rate > clk->rate);
743 774
744 return 0; 775 return 0;
745} 776}
@@ -956,7 +987,7 @@ int __init omap2_clk_init(void)
956 clk_init(&omap2_clk_functions); 987 clk_init(&omap2_clk_functions);
957 988
958 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) 989 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
959 clk_init_one(c->lk.clk); 990 clk_preinit(c->lk.clk);
960 991
961 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) 992 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
962 if (c->cpu & cpu_clkflg) { 993 if (c->cpu & cpu_clkflg) {