aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2009-06-19 21:08:26 -0400
committerpaul <paul@twilight.(none)>2009-06-19 21:09:31 -0400
commitc9812d042a21eb492a36cfabf9f41107f5ecee3d (patch)
treef9443de1d4534b0b56bd1b0ff56bfc6d78eb698d /arch/arm
parent2f135eaf182761bb9a5cbd5138a447b0ad2a1fef (diff)
OMAP3 clock: add a short delay when lowering CORE clk rate
When changing the SDRAM clock from 166MHz to 83MHz via the CORE DPLL M2 divider, add a short delay before returning to SDRAM to allow the SDRC time to stabilize. Without this delay, the system is prone to random panics upon re-entering SDRAM. This time delay varies based on MPU frequency. At 500MHz MPU frequency at room temperature, 64 loops seems to work okay; so add another 32 loops for environmental and process variation. Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/clock34xx.c30
-rw-r--r--arch/arm/mach-omap2/sram34xx.S20
-rw-r--r--arch/arm/plat-omap/include/mach/sram.h4
-rw-r--r--arch/arm/plat-omap/sram.c8
4 files changed, 44 insertions, 18 deletions
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 5458ab3bf65a..4bfa650bb34b 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -286,6 +286,20 @@ static struct omap_clk omap34xx_clks[] = {
286 286
287#define MIN_SDRC_DLL_LOCK_FREQ 83000000 287#define MIN_SDRC_DLL_LOCK_FREQ 83000000
288 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
289/** 303/**
290 * omap3_dpll_recalc - recalculate DPLL rate 304 * omap3_dpll_recalc - recalculate DPLL rate
291 * @clk: DPLL struct clk 305 * @clk: DPLL struct clk
@@ -709,7 +723,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
709{ 723{
710 u32 new_div = 0; 724 u32 new_div = 0;
711 u32 unlock_dll = 0; 725 u32 unlock_dll = 0;
712 unsigned long validrate, sdrcrate; 726 u32 c;
727 unsigned long validrate, sdrcrate, mpurate;
713 struct omap_sdrc_params *sp; 728 struct omap_sdrc_params *sp;
714 729
715 if (!clk || !rate) 730 if (!clk || !rate)
@@ -737,6 +752,17 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
737 unlock_dll = 1; 752 unlock_dll = 1;
738 } 753 }
739 754
755 /*
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
740 pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, 766 pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
741 validrate); 767 validrate);
742 pr_debug("clock: SDRC timing params used: %08x %08x %08x\n", 768 pr_debug("clock: SDRC timing params used: %08x %08x %08x\n",
@@ -747,7 +773,7 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
747 773
748 /* REVISIT: Add SDRC_MR changing to this code also */ 774 /* REVISIT: Add SDRC_MR changing to this code also */
749 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, 775 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
750 sp->actim_ctrlb, new_div, unlock_dll); 776 sp->actim_ctrlb, new_div, unlock_dll, c);
751 777
752 return 0; 778 return 0;
753} 779}
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index 84781a6cd263..8d4a88c30718 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -42,10 +42,14 @@
42 * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2 42 * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
43 * r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for 43 * r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for
44 * SDRC rates < 83MHz 44 * SDRC rates < 83MHz
45 * r5 = number of MPU cycles to wait for SDRC to stabilize after
46 * reprogramming the SDRC when switching to a slower MPU speed
47 *
45 */ 48 */
46ENTRY(omap3_sram_configure_core_dpll) 49ENTRY(omap3_sram_configure_core_dpll)
47 stmfd sp!, {r1-r12, lr} @ store regs to stack 50 stmfd sp!, {r1-r12, lr} @ store regs to stack
48 ldr r4, [sp, #52] @ pull extra args off the stack 51 ldr r4, [sp, #52] @ pull extra args off the stack
52 ldr r5, [sp, #56] @ load extra args from the stack
49 dsb @ flush buffered writes to interconnect 53 dsb @ flush buffered writes to interconnect
50 cmp r3, #0x2 54 cmp r3, #0x2
51 blne configure_sdrc 55 blne configure_sdrc
@@ -59,7 +63,11 @@ ENTRY(omap3_sram_configure_core_dpll)
59 bleq wait_dll_unlock 63 bleq wait_dll_unlock
60 blne wait_dll_lock 64 blne wait_dll_lock
61 cmp r3, #0x1 65 cmp r3, #0x1
62 blne configure_sdrc 66 beq return_to_sdram
67 bl configure_sdrc
68 mov r12, r5 @ if slowing, wait for SDRC to stabilize
69 bl wait_clk_stable
70return_to_sdram:
63 isb @ prevent speculative exec past here 71 isb @ prevent speculative exec past here
64 mov r0, #0 @ return value 72 mov r0, #0 @ return value
65 ldmfd sp!, {r1-r12, pc} @ restore regs and return 73 ldmfd sp!, {r1-r12, pc} @ restore regs and return
@@ -106,16 +114,6 @@ configure_core_dpll:
106wait_clk_stable: 114wait_clk_stable:
107 subs r12, r12, #1 115 subs r12, r12, #1
108 bne wait_clk_stable 116 bne wait_clk_stable
109 nop
110 nop
111 nop
112 nop
113 nop
114 nop
115 nop
116 nop
117 nop
118 nop
119 bx lr 117 bx lr
120enable_sdrc: 118enable_sdrc:
121 ldr r11, omap3_cm_iclken1_core 119 ldr r11, omap3_cm_iclken1_core
diff --git a/arch/arm/plat-omap/include/mach/sram.h b/arch/arm/plat-omap/include/mach/sram.h
index dca7c16ae903..c32fa0a220dc 100644
--- a/arch/arm/plat-omap/include/mach/sram.h
+++ b/arch/arm/plat-omap/include/mach/sram.h
@@ -24,7 +24,7 @@ extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
24extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, 24extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl,
25 u32 sdrc_actim_ctrla, 25 u32 sdrc_actim_ctrla,
26 u32 sdrc_actim_ctrlb, u32 m2, 26 u32 sdrc_actim_ctrlb, u32 m2,
27 u32 unlock_dll); 27 u32 unlock_dll, u32 f);
28 28
29/* Do not use these */ 29/* Do not use these */
30extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl); 30extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
@@ -62,7 +62,7 @@ extern unsigned long omap243x_sram_reprogram_sdrc_sz;
62extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl, 62extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl,
63 u32 sdrc_actim_ctrla, 63 u32 sdrc_actim_ctrla,
64 u32 sdrc_actim_ctrlb, u32 m2, 64 u32 sdrc_actim_ctrlb, u32 m2,
65 u32 unlock_dll); 65 u32 unlock_dll, u32 f);
66extern unsigned long omap3_sram_configure_core_dpll_sz; 66extern unsigned long omap3_sram_configure_core_dpll_sz;
67 67
68#endif 68#endif
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index a5b9bcd6b108..79c0f0254426 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -371,15 +371,17 @@ static inline int omap243x_sram_init(void)
371static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, 371static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl,
372 u32 sdrc_actim_ctrla, 372 u32 sdrc_actim_ctrla,
373 u32 sdrc_actim_ctrlb, 373 u32 sdrc_actim_ctrlb,
374 u32 m2, u32 unlock_dll); 374 u32 m2, u32 unlock_dll,
375 u32 f);
375u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, 376u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla,
376 u32 sdrc_actim_ctrlb, u32 m2, u32 unlock_dll) 377 u32 sdrc_actim_ctrlb, u32 m2, u32 unlock_dll,
378 u32 f)
377{ 379{
378 BUG_ON(!_omap3_sram_configure_core_dpll); 380 BUG_ON(!_omap3_sram_configure_core_dpll);
379 return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, 381 return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl,
380 sdrc_actim_ctrla, 382 sdrc_actim_ctrla,
381 sdrc_actim_ctrlb, m2, 383 sdrc_actim_ctrlb, m2,
382 unlock_dll); 384 unlock_dll, f);
383} 385}
384 386
385/* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */ 387/* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */