* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 16:40 ` jean.pihet at newoldbits.com
0 siblings, 0 replies; 26+ messages in thread
From: jean.pihet @ 2011-06-29 16:40 UTC (permalink / raw)
To: khilman, linux-omap, santosh.shilimkar, Russell King, linux-arm-kernel
Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
However only a small part of the code really needs to run from internal SRAM.
This fix lets most of the ASM idle code run from the DDR
in order to minimize the SRAM usage and the overhead in the code copy.
The only pieces of code that are mandatory in SRAM are:
- the i443 erratum WA,
- the i581 erratum WA,
- the security extension code.
SRAM usage:
- original code:
. 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
. 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
. 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
. 108 bytes for save_secure_ram_context (used on HS parts only).
With this fix the usage for suspend/resume in RETention goes down 288 bytes,
so the gain in SRAM usage for suspend/resume is 564 bytes.
Also fixed the SRAM initialization sequence to avoid an unnecessary
copy to SRAM at boot time and for readability.
Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/pm.h | 20 ++-
arch/arm/mach-omap2/pm34xx.c | 20 ++--
arch/arm/mach-omap2/sleep34xx.S | 303 ++++++++++++++++++++++----------------
arch/arm/plat-omap/sram.c | 15 +--
4 files changed, 206 insertions(+), 152 deletions(-)
Rebased on the suspend branch of rmk's tree
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..a4ec213 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);
#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
+/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
+extern unsigned int omap24xx_cpu_suspend_sz;
+
+/* 3xxx */
extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
#define PM_RTA_ERRATUM_i608 (1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3e9a13e..e1c79ba 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -78,9 +78,8 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -309,7 +308,7 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- _omap_sram_idle(omap3_arm_context, save_state);
+ omap34xx_cpu_suspend(omap3_arm_context, save_state);
}
void omap_sram_idle(void)
@@ -328,9 +327,6 @@ void omap_sram_idle(void)
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
- if (!_omap_sram_idle)
- return;
-
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
pwrdm_clear_all_prev_pwrst(neon_pwrdm);
pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -826,10 +822,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
void omap_push_sram_idle(void)
{
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
@@ -894,7 +897,6 @@ static int __init omap3_pm_init(void)
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
- omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index d18f52e..17dbc5a 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -139,8 +139,10 @@ ENTRY(save_secure_ram_context_sz)
*
*
* Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ * pointers in SDRAM or SRAM are called depending on the desired low power
+ * target state.
* - when the OMAP wakes up it continues at different execution points
* depending on the low power mode (non-OFF vs OFF modes),
* cf. 'Resume path for xxx mode' comments.
@@ -158,9 +160,15 @@ ENTRY(omap34xx_cpu_suspend)
* 3 - Both L1 and L2 lost and logic lost
*/
- /* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
- beq omap3_do_wfi
+ /*
+ * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+ * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+ */
+ ldr r4, omap3_do_wfi_sram_addr
+ ldr r5, [r4]
+ cmp r1, #0x0 @ If no context save required,
+ bxeq r5 @ jump to the WFI code in SRAM
+
/* Otherwise fall through to the save context code */
save_context_wfi:
@@ -213,7 +221,32 @@ save_context_wfi:
THUMB( nop )
.arm
-omap3_do_wfi:
+ b omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+ .word omap3_do_wfi_sram
+kernel_flush:
+ .word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+ .align 3
+ENTRY(omap3_do_wfi)
ldr r4, sdrc_power @ read the SDRC_POWER register
ldr r5, [r4] @ read the contents of SDRC_POWER
orr r5, r5, #0x40 @ enable self refresh on idle req
@@ -245,8 +278,86 @@ omap3_do_wfi:
nop
nop
nop
- bl wait_sdrc_ok
+/*
+ * This function implements the erratum ID i581 WA:
+ * SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+ ldr r4, cm_idlest_ckgen
+wait_dpll3_lock:
+ ldr r5, [r4]
+ tst r5, #1
+ beq wait_dpll3_lock
+
+ ldr r4, cm_idlest1_core
+wait_sdrc_ready:
+ ldr r5, [r4]
+ tst r5, #0x2
+ bne wait_sdrc_ready
+ /* allow DLL powerdown upon hw idle req */
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+ adr r7, kick_counter
+wait_dll_lock_timed:
+ ldr r4, wait_dll_lock_counter
+ add r4, r4, #1
+ str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+wait_dll_lock:
+ subs r6, r6, #0x1
+ beq kick_dll
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ b exit_nonoff_modes @ Return when locked
+
+ /* disable/reenable DLL if not locked */
+kick_dll:
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ mov r6, r5
+ bic r6, #(1<<3) @ disable dll
+ str r6, [r4]
+ dsb
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+ ldr r4, kick_counter
+ add r4, r4, #1
+ str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+exit_nonoff_modes:
+ /* Re-enable C-bit if needed */
mrc p15, 0, r0, c1, c0, 0
tst r0, #(1 << 2) @ Check C bit enabled?
orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
@@ -260,6 +371,31 @@ omap3_do_wfi:
*/
ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+/*
+ * Local variables
+ */
+sdrc_power:
+ .word SDRC_POWER_V
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+ .word CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+ /*
+ * When exporting to userspace while the counters are in SRAM,
+ * these 2 words need to be at the end to facilitate retrival!
+ */
+kick_counter:
+ .word 0
+wait_dll_lock_counter:
+ .word 0
+
+ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
+
/*
* ==============================
@@ -275,13 +411,17 @@ omap3_do_wfi:
* restore_es3: applies to 34xx >= ES3.0
* restore_3630: applies to 36xx
* restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ * from SDRAM, without MMU, without the caches and prediction.
+ * Also the SRAM content has been cleared.
*/
ENTRY(omap3_restore_es3)
ldr r5, pm_prepwstst_core_p
ldr r4, [r5]
and r4, r4, #0x3
cmp r4, #0x0 @ Check if previous power state of CORE is OFF
- bne omap3_restore
+ bne omap3_restore @ Fall through to OMAP3 common code
adr r0, es3_sdrc_fix
ldr r1, sram_base
ldr r2, es3_sdrc_fix_sz
@@ -293,7 +433,7 @@ copy_to_sram:
bne copy_to_sram
ldr r1, sram_base
blx r1
- b omap3_restore
+ b omap3_restore @ Fall through to OMAP3 common code
ENDPROC(omap3_restore_es3)
ENTRY(omap3_restore_3630)
@@ -301,7 +441,7 @@ ENTRY(omap3_restore_3630)
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if previous power state of CORE is OFF
- bne omap3_restore
+ bne omap3_restore @ Fall through to OMAP3 common code
/* Disable RTA before giving control */
ldr r1, control_mem_rta
mov r2, #OMAP36XX_RTA_DISABLE
@@ -405,10 +545,31 @@ ENDPROC(omap3_restore)
.ltorg
/*
+ * Local variables
+ */
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+ .word PM_PWSTCTRL_MPU_P
+scratchpad_base:
+ .word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
+control_stat:
+ .word CONTROL_STAT
+control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+ .word 0
+
+/*
* Internal functions
*/
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/*
+ * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
+ */
.text
.align 3
ENTRY(es3_sdrc_fix)
@@ -438,6 +599,9 @@ ENTRY(es3_sdrc_fix)
str r5, [r4] @ kick off refreshes
bx lr
+/*
+ * Local variables
+ */
.align
sdrc_syscfg:
.word SDRC_SYSCONFIG_P
@@ -456,120 +620,3 @@ sdrc_manual_1:
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
.word . - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- * SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
- ldr r4, cm_idlest_ckgen
-wait_dpll3_lock:
- ldr r5, [r4]
- tst r5, #1
- beq wait_dpll3_lock
-
- ldr r4, cm_idlest1_core
-wait_sdrc_ready:
- ldr r5, [r4]
- tst r5, #0x2
- bne wait_sdrc_ready
- /* allow DLL powerdown upon hw idle req */
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
- /* Is dll in lock mode? */
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- tst r5, #0x4
- bxne lr @ Return if locked
- /* wait till dll locks */
- adr r7, kick_counter
-wait_dll_lock_timed:
- ldr r4, wait_dll_lock_counter
- add r4, r4, #1
- str r4, [r7, #wait_dll_lock_counter - kick_counter]
- ldr r4, sdrc_dlla_status
- /* Wait 20uS for lock */
- mov r6, #8
-wait_dll_lock:
- subs r6, r6, #0x1
- beq kick_dll
- ldr r5, [r4]
- and r5, r5, #0x4
- cmp r5, #0x4
- bne wait_dll_lock
- bx lr @ Return when locked
-
- /* disable/reenable DLL if not locked */
-kick_dll:
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- mov r6, r5
- bic r6, #(1<<3) @ disable dll
- str r6, [r4]
- dsb
- orr r6, r6, #(1<<3) @ enable dll
- str r6, [r4]
- dsb
- ldr r4, kick_counter
- add r4, r4, #1
- str r4, [r7] @ kick_counter
- b wait_dll_lock_timed
-
- .align
-cm_idlest1_core:
- .word CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
- .word CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
- .word SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
- .word SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
- .word PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
- .word PM_PWSTCTRL_MPU_P
-scratchpad_base:
- .word SCRATCHPAD_BASE_P
-sram_base:
- .word SRAM_BASE_P + 0x8000
-sdrc_power:
- .word SDRC_POWER_V
-control_stat:
- .word CONTROL_STAT
-control_mem_rta:
- .word CONTROL_MEM_RTA_CTRL
-kernel_flush:
- .word v7_flush_dcache_all
-l2dis_3630:
- .word 0
- /*
- * When exporting to userspace while the counters are in SRAM,
- * these 2 words need to be at the end to facilitate retrival!
- */
-kick_counter:
- .word 0
-wait_dll_lock_counter:
- .word 0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
- .word . - omap34xx_cpu_suspend
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b..363c91e 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
}
#endif /* CONFIG_PM */
-static int __init omap34xx_sram_init(void)
-{
- _omap3_sram_configure_core_dpll =
- omap_sram_push(omap3_sram_configure_core_dpll,
- omap3_sram_configure_core_dpll_sz);
- omap_push_sram_idle();
- return 0;
-}
-#else
+#endif /* CONFIG_ARCH_OMAP3 */
+
static inline int omap34xx_sram_init(void)
{
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+ omap3_sram_restore_context();
+#endif
return 0;
}
-#endif
int __init omap_sram_init(void)
{
--
1.7.4.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 16:40 ` jean.pihet at newoldbits.com
0 siblings, 0 replies; 26+ messages in thread
From: jean.pihet at newoldbits.com @ 2011-06-29 16:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Jean Pihet <j-pihet@ti.com>
Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
However only a small part of the code really needs to run from internal SRAM.
This fix lets most of the ASM idle code run from the DDR
in order to minimize the SRAM usage and the overhead in the code copy.
The only pieces of code that are mandatory in SRAM are:
- the i443 erratum WA,
- the i581 erratum WA,
- the security extension code.
SRAM usage:
- original code:
. 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
. 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
. 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
. 108 bytes for save_secure_ram_context (used on HS parts only).
With this fix the usage for suspend/resume in RETention goes down 288 bytes,
so the gain in SRAM usage for suspend/resume is 564 bytes.
Also fixed the SRAM initialization sequence to avoid an unnecessary
copy to SRAM at boot time and for readability.
Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/pm.h | 20 ++-
arch/arm/mach-omap2/pm34xx.c | 20 ++--
arch/arm/mach-omap2/sleep34xx.S | 303 ++++++++++++++++++++++----------------
arch/arm/plat-omap/sram.c | 15 +--
4 files changed, 206 insertions(+), 152 deletions(-)
Rebased on the suspend branch of rmk's tree
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..a4ec213 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);
#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
+/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
+extern unsigned int omap24xx_cpu_suspend_sz;
+
+/* 3xxx */
extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
#define PM_RTA_ERRATUM_i608 (1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3e9a13e..e1c79ba 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -78,9 +78,8 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -309,7 +308,7 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- _omap_sram_idle(omap3_arm_context, save_state);
+ omap34xx_cpu_suspend(omap3_arm_context, save_state);
}
void omap_sram_idle(void)
@@ -328,9 +327,6 @@ void omap_sram_idle(void)
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
- if (!_omap_sram_idle)
- return;
-
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
pwrdm_clear_all_prev_pwrst(neon_pwrdm);
pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -826,10 +822,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
void omap_push_sram_idle(void)
{
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
@@ -894,7 +897,6 @@ static int __init omap3_pm_init(void)
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
- omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index d18f52e..17dbc5a 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -139,8 +139,10 @@ ENTRY(save_secure_ram_context_sz)
*
*
* Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ * pointers in SDRAM or SRAM are called depending on the desired low power
+ * target state.
* - when the OMAP wakes up it continues@different execution points
* depending on the low power mode (non-OFF vs OFF modes),
* cf. 'Resume path for xxx mode' comments.
@@ -158,9 +160,15 @@ ENTRY(omap34xx_cpu_suspend)
* 3 - Both L1 and L2 lost and logic lost
*/
- /* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
- beq omap3_do_wfi
+ /*
+ * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+ * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+ */
+ ldr r4, omap3_do_wfi_sram_addr
+ ldr r5, [r4]
+ cmp r1, #0x0 @ If no context save required,
+ bxeq r5 @ jump to the WFI code in SRAM
+
/* Otherwise fall through to the save context code */
save_context_wfi:
@@ -213,7 +221,32 @@ save_context_wfi:
THUMB( nop )
.arm
-omap3_do_wfi:
+ b omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+ .word omap3_do_wfi_sram
+kernel_flush:
+ .word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+ .align 3
+ENTRY(omap3_do_wfi)
ldr r4, sdrc_power @ read the SDRC_POWER register
ldr r5, [r4] @ read the contents of SDRC_POWER
orr r5, r5, #0x40 @ enable self refresh on idle req
@@ -245,8 +278,86 @@ omap3_do_wfi:
nop
nop
nop
- bl wait_sdrc_ok
+/*
+ * This function implements the erratum ID i581 WA:
+ * SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+ ldr r4, cm_idlest_ckgen
+wait_dpll3_lock:
+ ldr r5, [r4]
+ tst r5, #1
+ beq wait_dpll3_lock
+
+ ldr r4, cm_idlest1_core
+wait_sdrc_ready:
+ ldr r5, [r4]
+ tst r5, #0x2
+ bne wait_sdrc_ready
+ /* allow DLL powerdown upon hw idle req */
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+ adr r7, kick_counter
+wait_dll_lock_timed:
+ ldr r4, wait_dll_lock_counter
+ add r4, r4, #1
+ str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+wait_dll_lock:
+ subs r6, r6, #0x1
+ beq kick_dll
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ b exit_nonoff_modes @ Return when locked
+
+ /* disable/reenable DLL if not locked */
+kick_dll:
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ mov r6, r5
+ bic r6, #(1<<3) @ disable dll
+ str r6, [r4]
+ dsb
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+ ldr r4, kick_counter
+ add r4, r4, #1
+ str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+exit_nonoff_modes:
+ /* Re-enable C-bit if needed */
mrc p15, 0, r0, c1, c0, 0
tst r0, #(1 << 2) @ Check C bit enabled?
orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
@@ -260,6 +371,31 @@ omap3_do_wfi:
*/
ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+/*
+ * Local variables
+ */
+sdrc_power:
+ .word SDRC_POWER_V
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+ .word CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+ /*
+ * When exporting to userspace while the counters are in SRAM,
+ * these 2 words need to be@the end to facilitate retrival!
+ */
+kick_counter:
+ .word 0
+wait_dll_lock_counter:
+ .word 0
+
+ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
+
/*
* ==============================
@@ -275,13 +411,17 @@ omap3_do_wfi:
* restore_es3: applies to 34xx >= ES3.0
* restore_3630: applies to 36xx
* restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ * from SDRAM, without MMU, without the caches and prediction.
+ * Also the SRAM content has been cleared.
*/
ENTRY(omap3_restore_es3)
ldr r5, pm_prepwstst_core_p
ldr r4, [r5]
and r4, r4, #0x3
cmp r4, #0x0 @ Check if previous power state of CORE is OFF
- bne omap3_restore
+ bne omap3_restore @ Fall through to OMAP3 common code
adr r0, es3_sdrc_fix
ldr r1, sram_base
ldr r2, es3_sdrc_fix_sz
@@ -293,7 +433,7 @@ copy_to_sram:
bne copy_to_sram
ldr r1, sram_base
blx r1
- b omap3_restore
+ b omap3_restore @ Fall through to OMAP3 common code
ENDPROC(omap3_restore_es3)
ENTRY(omap3_restore_3630)
@@ -301,7 +441,7 @@ ENTRY(omap3_restore_3630)
ldr r2, [r1]
and r2, r2, #0x3
cmp r2, #0x0 @ Check if previous power state of CORE is OFF
- bne omap3_restore
+ bne omap3_restore @ Fall through to OMAP3 common code
/* Disable RTA before giving control */
ldr r1, control_mem_rta
mov r2, #OMAP36XX_RTA_DISABLE
@@ -405,10 +545,31 @@ ENDPROC(omap3_restore)
.ltorg
/*
+ * Local variables
+ */
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+ .word PM_PWSTCTRL_MPU_P
+scratchpad_base:
+ .word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
+control_stat:
+ .word CONTROL_STAT
+control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+ .word 0
+
+/*
* Internal functions
*/
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/*
+ * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
+ */
.text
.align 3
ENTRY(es3_sdrc_fix)
@@ -438,6 +599,9 @@ ENTRY(es3_sdrc_fix)
str r5, [r4] @ kick off refreshes
bx lr
+/*
+ * Local variables
+ */
.align
sdrc_syscfg:
.word SDRC_SYSCONFIG_P
@@ -456,120 +620,3 @@ sdrc_manual_1:
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
.word . - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- * SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
- ldr r4, cm_idlest_ckgen
-wait_dpll3_lock:
- ldr r5, [r4]
- tst r5, #1
- beq wait_dpll3_lock
-
- ldr r4, cm_idlest1_core
-wait_sdrc_ready:
- ldr r5, [r4]
- tst r5, #0x2
- bne wait_sdrc_ready
- /* allow DLL powerdown upon hw idle req */
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
- /* Is dll in lock mode? */
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- tst r5, #0x4
- bxne lr @ Return if locked
- /* wait till dll locks */
- adr r7, kick_counter
-wait_dll_lock_timed:
- ldr r4, wait_dll_lock_counter
- add r4, r4, #1
- str r4, [r7, #wait_dll_lock_counter - kick_counter]
- ldr r4, sdrc_dlla_status
- /* Wait 20uS for lock */
- mov r6, #8
-wait_dll_lock:
- subs r6, r6, #0x1
- beq kick_dll
- ldr r5, [r4]
- and r5, r5, #0x4
- cmp r5, #0x4
- bne wait_dll_lock
- bx lr @ Return when locked
-
- /* disable/reenable DLL if not locked */
-kick_dll:
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- mov r6, r5
- bic r6, #(1<<3) @ disable dll
- str r6, [r4]
- dsb
- orr r6, r6, #(1<<3) @ enable dll
- str r6, [r4]
- dsb
- ldr r4, kick_counter
- add r4, r4, #1
- str r4, [r7] @ kick_counter
- b wait_dll_lock_timed
-
- .align
-cm_idlest1_core:
- .word CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
- .word CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
- .word SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
- .word SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
- .word PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
- .word PM_PWSTCTRL_MPU_P
-scratchpad_base:
- .word SCRATCHPAD_BASE_P
-sram_base:
- .word SRAM_BASE_P + 0x8000
-sdrc_power:
- .word SDRC_POWER_V
-control_stat:
- .word CONTROL_STAT
-control_mem_rta:
- .word CONTROL_MEM_RTA_CTRL
-kernel_flush:
- .word v7_flush_dcache_all
-l2dis_3630:
- .word 0
- /*
- * When exporting to userspace while the counters are in SRAM,
- * these 2 words need to be@the end to facilitate retrival!
- */
-kick_counter:
- .word 0
-wait_dll_lock_counter:
- .word 0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
- .word . - omap34xx_cpu_suspend
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b..363c91e 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
}
#endif /* CONFIG_PM */
-static int __init omap34xx_sram_init(void)
-{
- _omap3_sram_configure_core_dpll =
- omap_sram_push(omap3_sram_configure_core_dpll,
- omap3_sram_configure_core_dpll_sz);
- omap_push_sram_idle();
- return 0;
-}
-#else
+#endif /* CONFIG_ARCH_OMAP3 */
+
static inline int omap34xx_sram_init(void)
{
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+ omap3_sram_restore_context();
+#endif
return 0;
}
-#endif
int __init omap_sram_init(void)
{
--
1.7.4.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 16:40 ` jean.pihet at newoldbits.com
@ 2011-06-29 17:29 ` Kevin Hilman
-1 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 17:29 UTC (permalink / raw)
To: jean.pihet
Cc: linux-omap, santosh.shilimkar, Russell King, linux-arm-kernel,
Jean Pihet
jean.pihet@newoldbits.com writes:
> From: Jean Pihet <j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage and the overhead in the code copy.
>
> The only pieces of code that are mandatory in SRAM are:
> - the i443 erratum WA,
> - the i581 erratum WA,
> - the security extension code.
>
> SRAM usage:
> - original code:
> . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
> . 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
> . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
> . 108 bytes for save_secure_ram_context (used on HS parts only).
>
> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
> so the gain in SRAM usage for suspend/resume is 564 bytes.
>
> Also fixed the SRAM initialization sequence to avoid an unnecessary
> copy to SRAM at boot time and for readability.
>
> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Also tested retention and off on 3430/n900, 3530/Overo and 3630/Zoom3
Tested-by: Kevin Hilman <khilman@ti.com>
Russell, if you're OK with it, can you add it to your suspend branch for
the upcoming merge window?
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 17:29 ` Kevin Hilman
0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 17:29 UTC (permalink / raw)
To: linux-arm-kernel
jean.pihet at newoldbits.com writes:
> From: Jean Pihet <j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage and the overhead in the code copy.
>
> The only pieces of code that are mandatory in SRAM are:
> - the i443 erratum WA,
> - the i581 erratum WA,
> - the security extension code.
>
> SRAM usage:
> - original code:
> . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
> . 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
> . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
> . 108 bytes for save_secure_ram_context (used on HS parts only).
>
> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
> so the gain in SRAM usage for suspend/resume is 564 bytes.
>
> Also fixed the SRAM initialization sequence to avoid an unnecessary
> copy to SRAM at boot time and for readability.
>
> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Also tested retention and off on 3430/n900, 3530/Overo and 3630/Zoom3
Tested-by: Kevin Hilman <khilman@ti.com>
Russell, if you're OK with it, can you add it to your suspend branch for
the upcoming merge window?
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 17:29 ` Kevin Hilman
@ 2011-06-29 17:48 ` Jean Pihet
-1 siblings, 0 replies; 26+ messages in thread
From: Jean Pihet @ 2011-06-29 17:48 UTC (permalink / raw)
To: Kevin Hilman
Cc: linux-omap, santosh.shilimkar, Russell King, linux-arm-kernel,
Jean Pihet
On Wed, Jun 29, 2011 at 7:29 PM, Kevin Hilman <khilman@ti.com> wrote:
> jean.pihet@newoldbits.com writes:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
>> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
>> However only a small part of the code really needs to run from internal SRAM.
>>
>> This fix lets most of the ASM idle code run from the DDR
>> in order to minimize the SRAM usage and the overhead in the code copy.
>>
>> The only pieces of code that are mandatory in SRAM are:
>> - the i443 erratum WA,
>> - the i581 erratum WA,
>> - the security extension code.
>>
>> SRAM usage:
>> - original code:
>> . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
>> . 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
>> . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
>> . 108 bytes for save_secure_ram_context (used on HS parts only).
>>
>> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
>> so the gain in SRAM usage for suspend/resume is 564 bytes.
>>
>> Also fixed the SRAM initialization sequence to avoid an unnecessary
>> copy to SRAM at boot time and for readability.
>>
>> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
>
> Also tested retention and off on 3430/n900, 3530/Overo and 3630/Zoom3
>
> Tested-by: Kevin Hilman <khilman@ti.com>
Thanks for the extensive testing!
Regards,
Jean
>
> Russell, if you're OK with it, can you add it to your suspend branch for
> the upcoming merge window?
>
> Kevin
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 17:48 ` Jean Pihet
0 siblings, 0 replies; 26+ messages in thread
From: Jean Pihet @ 2011-06-29 17:48 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 29, 2011 at 7:29 PM, Kevin Hilman <khilman@ti.com> wrote:
> jean.pihet at newoldbits.com writes:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
>> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
>> However only a small part of the code really needs to run from internal SRAM.
>>
>> This fix lets most of the ASM idle code run from the DDR
>> in order to minimize the SRAM usage and the overhead in the code copy.
>>
>> The only pieces of code that are mandatory in SRAM are:
>> - the i443 erratum WA,
>> - the i581 erratum WA,
>> - the security extension code.
>>
>> SRAM usage:
>> - original code:
>> ? . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
>> ? . 852 bytes for omap_sram_idle (used by suspend/resume in RETention),
>> ? . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
>> ? . 108 bytes for save_secure_ram_context (used on HS parts only).
>>
>> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
>> so the gain in SRAM usage for suspend/resume is 564 bytes.
>>
>> Also fixed the SRAM initialization sequence to avoid an unnecessary
>> copy to SRAM at boot time and for readability.
>>
>> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
>
> Also tested retention and off on 3430/n900, 3530/Overo and 3630/Zoom3
>
> Tested-by: Kevin Hilman <khilman@ti.com>
Thanks for the extensive testing!
Regards,
Jean
>
> Russell, if you're OK with it, can you add it to your suspend branch for
> the upcoming merge window?
>
> Kevin
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 17:29 ` Kevin Hilman
@ 2011-06-29 18:05 ` Russell King - ARM Linux
-1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 18:05 UTC (permalink / raw)
To: Kevin Hilman
Cc: jean.pihet, linux-omap, santosh.shilimkar, linux-arm-kernel, Jean Pihet
On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
> Russell, if you're OK with it, can you add it to your suspend branch for
> the upcoming merge window?
Yes - though I think we can go a little bit further - this patch is on
top of my code so far, and is untested. There isn't a need for the
saving of these registers to be in assembly because we can read them
just as easily from C code.
Comments?
arch/arm/mach-omap2/pm.h | 2 +-
arch/arm/mach-omap2/pm34xx.c | 19 +++++++++++++++++--
arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
3 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..4984cca 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void omap34xx_cpu_suspend(int save_state);
extern int save_secure_ram_context(u32 *addr);
extern void omap3_save_scratchpad_contents(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3e9a13e..6366352 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -78,7 +78,7 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
+static void (*_omap_sram_idle)(int save_state);
static int (*_omap_save_secure_sram)(u32 *addr);
@@ -307,9 +307,22 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void omap34xx_save_context(u32 *save)
+{
+ u32 val;
+
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- _omap_sram_idle(omap3_arm_context, save_state);
+ _omap_sram_idle(save_state);
}
void omap_sram_idle(void)
@@ -412,6 +425,8 @@ void omap_sram_idle(void)
* get saved. The rest is placed on the stack, and restored
* from there before resuming.
*/
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
if (save_state == 1 || save_state == 3)
cpu_suspend(save_state, omap34xx_do_sram_idle);
else
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index d18f52e..3335753 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -150,8 +150,7 @@ ENTRY(omap34xx_cpu_suspend)
stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
@@ -159,18 +158,11 @@ ENTRY(omap34xx_cpu_suspend)
*/
/* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
+ cmp r0, #0x0
beq omap3_do_wfi
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
/*
* jump out to kernel flush routine
* - reuse that code is better
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 18:05 ` Russell King - ARM Linux
0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 18:05 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
> Russell, if you're OK with it, can you add it to your suspend branch for
> the upcoming merge window?
Yes - though I think we can go a little bit further - this patch is on
top of my code so far, and is untested. There isn't a need for the
saving of these registers to be in assembly because we can read them
just as easily from C code.
Comments?
arch/arm/mach-omap2/pm.h | 2 +-
arch/arm/mach-omap2/pm34xx.c | 19 +++++++++++++++++--
arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
3 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..4984cca 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void omap34xx_cpu_suspend(int save_state);
extern int save_secure_ram_context(u32 *addr);
extern void omap3_save_scratchpad_contents(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3e9a13e..6366352 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -78,7 +78,7 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
+static void (*_omap_sram_idle)(int save_state);
static int (*_omap_save_secure_sram)(u32 *addr);
@@ -307,9 +307,22 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void omap34xx_save_context(u32 *save)
+{
+ u32 val;
+
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- _omap_sram_idle(omap3_arm_context, save_state);
+ _omap_sram_idle(save_state);
}
void omap_sram_idle(void)
@@ -412,6 +425,8 @@ void omap_sram_idle(void)
* get saved. The rest is placed on the stack, and restored
* from there before resuming.
*/
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
if (save_state == 1 || save_state == 3)
cpu_suspend(save_state, omap34xx_do_sram_idle);
else
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index d18f52e..3335753 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -150,8 +150,7 @@ ENTRY(omap34xx_cpu_suspend)
stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
@@ -159,18 +158,11 @@ ENTRY(omap34xx_cpu_suspend)
*/
/* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
+ cmp r0, #0x0
beq omap3_do_wfi
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
/*
* jump out to kernel flush routine
* - reuse that code is better
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 18:05 ` Russell King - ARM Linux
@ 2011-06-29 19:06 ` Kevin Hilman
-1 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 19:06 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: jean.pihet, linux-omap, santosh.shilimkar, linux-arm-kernel, Jean Pihet
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
> On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
>> Russell, if you're OK with it, can you add it to your suspend branch for
>> the upcoming merge window?
>
> Yes - though I think we can go a little bit further - this patch is on
> top of my code so far, and is untested. There isn't a need for the
> saving of these registers to be in assembly because we can read them
> just as easily from C code.
Indeed
> Comments?
Looks good to me (although untested) care to respin on top of $SUBJECT
patch?
Minor comments below...
> arch/arm/mach-omap2/pm.h | 2 +-
> arch/arm/mach-omap2/pm34xx.c | 19 +++++++++++++++++--
> arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
> 3 files changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 45bcfce..4984cca 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
>
> extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
> void __iomem *sdrc_power);
> -extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
> +extern void omap34xx_cpu_suspend(int save_state);
> extern int save_secure_ram_context(u32 *addr);
> extern void omap3_save_scratchpad_contents(void);
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 3e9a13e..6366352 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -78,7 +78,7 @@ struct power_state {
>
> static LIST_HEAD(pwrst_list);
>
> -static void (*_omap_sram_idle)(u32 *addr, int save_state);
> +static void (*_omap_sram_idle)(int save_state);
>
> static int (*_omap_save_secure_sram)(u32 *addr);
>
> @@ -307,9 +307,22 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +static void omap34xx_save_context(u32 *save)
> +{
> + u32 val;
> +
> + asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
Minor: for those of us who don't have all these registers memorized when
looking at the assembly, maybe keeping the original comments (e.g. "Read
AUX
> + *save++ = 1;
> + *save++ = val;
> +
> + asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
> + *save++ = 1;
> + *save++ = val;
> +}
> +
> static void omap34xx_do_sram_idle(unsigned long save_state)
> {
> - _omap_sram_idle(omap3_arm_context, save_state);
> + _omap_sram_idle(save_state);
> }
>
> void omap_sram_idle(void)
> @@ -412,6 +425,8 @@ void omap_sram_idle(void)
> * get saved. The rest is placed on the stack, and restored
> * from there before resuming.
> */
> + if (save_state)
> + omap34xx_save_context(omap3_arm_context);
> if (save_state == 1 || save_state == 3)
> cpu_suspend(save_state, omap34xx_do_sram_idle);
> else
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
> index d18f52e..3335753 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -150,8 +150,7 @@ ENTRY(omap34xx_cpu_suspend)
> stmfd sp!, {r4 - r11, lr} @ save registers on stack
>
> /*
> - * r0 contains CPU context save/restore pointer in sdram
> - * r1 contains information about saving context:
> + * r0 contains information about saving context:
> * 0 - No context lost
> * 1 - Only L1 and logic lost
> * 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
> @@ -159,18 +158,11 @@ ENTRY(omap34xx_cpu_suspend)
> */
>
> /* Directly jump to WFI is the context save is not required */
> - cmp r1, #0x0
> + cmp r0, #0x0
> beq omap3_do_wfi
>
> /* Otherwise fall through to the save context code */
> save_context_wfi:
> - mov r8, r0 @ Store SDRAM address in r8
> - mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
> - mov r4, #0x1 @ Number of parameters for restore call
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> - mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> -
> /*
> * jump out to kernel flush routine
> * - reuse that code is better
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 19:06 ` Kevin Hilman
0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
> On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
>> Russell, if you're OK with it, can you add it to your suspend branch for
>> the upcoming merge window?
>
> Yes - though I think we can go a little bit further - this patch is on
> top of my code so far, and is untested. There isn't a need for the
> saving of these registers to be in assembly because we can read them
> just as easily from C code.
Indeed
> Comments?
Looks good to me (although untested) care to respin on top of $SUBJECT
patch?
Minor comments below...
> arch/arm/mach-omap2/pm.h | 2 +-
> arch/arm/mach-omap2/pm34xx.c | 19 +++++++++++++++++--
> arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
> 3 files changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 45bcfce..4984cca 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
>
> extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
> void __iomem *sdrc_power);
> -extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
> +extern void omap34xx_cpu_suspend(int save_state);
> extern int save_secure_ram_context(u32 *addr);
> extern void omap3_save_scratchpad_contents(void);
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 3e9a13e..6366352 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -78,7 +78,7 @@ struct power_state {
>
> static LIST_HEAD(pwrst_list);
>
> -static void (*_omap_sram_idle)(u32 *addr, int save_state);
> +static void (*_omap_sram_idle)(int save_state);
>
> static int (*_omap_save_secure_sram)(u32 *addr);
>
> @@ -307,9 +307,22 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +static void omap34xx_save_context(u32 *save)
> +{
> + u32 val;
> +
> + asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
Minor: for those of us who don't have all these registers memorized when
looking at the assembly, maybe keeping the original comments (e.g. "Read
AUX
> + *save++ = 1;
> + *save++ = val;
> +
> + asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
> + *save++ = 1;
> + *save++ = val;
> +}
> +
> static void omap34xx_do_sram_idle(unsigned long save_state)
> {
> - _omap_sram_idle(omap3_arm_context, save_state);
> + _omap_sram_idle(save_state);
> }
>
> void omap_sram_idle(void)
> @@ -412,6 +425,8 @@ void omap_sram_idle(void)
> * get saved. The rest is placed on the stack, and restored
> * from there before resuming.
> */
> + if (save_state)
> + omap34xx_save_context(omap3_arm_context);
> if (save_state == 1 || save_state == 3)
> cpu_suspend(save_state, omap34xx_do_sram_idle);
> else
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
> index d18f52e..3335753 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -150,8 +150,7 @@ ENTRY(omap34xx_cpu_suspend)
> stmfd sp!, {r4 - r11, lr} @ save registers on stack
>
> /*
> - * r0 contains CPU context save/restore pointer in sdram
> - * r1 contains information about saving context:
> + * r0 contains information about saving context:
> * 0 - No context lost
> * 1 - Only L1 and logic lost
> * 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
> @@ -159,18 +158,11 @@ ENTRY(omap34xx_cpu_suspend)
> */
>
> /* Directly jump to WFI is the context save is not required */
> - cmp r1, #0x0
> + cmp r0, #0x0
> beq omap3_do_wfi
>
> /* Otherwise fall through to the save context code */
> save_context_wfi:
> - mov r8, r0 @ Store SDRAM address in r8
> - mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
> - mov r4, #0x1 @ Number of parameters for restore call
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> - mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> -
> /*
> * jump out to kernel flush routine
> * - reuse that code is better
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 16:40 ` jean.pihet at newoldbits.com
@ 2011-06-29 21:45 ` Russell King - ARM Linux
-1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 21:45 UTC (permalink / raw)
To: jean.pihet
Cc: khilman, linux-omap, santosh.shilimkar, linux-arm-kernel, Jean Pihet
On Wed, Jun 29, 2011 at 06:40:23PM +0200, jean.pihet@newoldbits.com wrote:
> @@ -309,7 +308,7 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
>
> static void omap34xx_do_sram_idle(unsigned long save_state)
> {
> - _omap_sram_idle(omap3_arm_context, save_state);
> + omap34xx_cpu_suspend(omap3_arm_context, save_state);
Actually, this should be called omap34xx_soc_suspend() or
omap34xx_finish_suspend() - finish_suspend() reflects the naming
of other such functions elsewhere.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 21:45 ` Russell King - ARM Linux
0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 21:45 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 29, 2011 at 06:40:23PM +0200, jean.pihet at newoldbits.com wrote:
> @@ -309,7 +308,7 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
>
> static void omap34xx_do_sram_idle(unsigned long save_state)
> {
> - _omap_sram_idle(omap3_arm_context, save_state);
> + omap34xx_cpu_suspend(omap3_arm_context, save_state);
Actually, this should be called omap34xx_soc_suspend() or
omap34xx_finish_suspend() - finish_suspend() reflects the naming
of other such functions elsewhere.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 19:06 ` Kevin Hilman
@ 2011-06-29 21:54 ` Russell King - ARM Linux
-1 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 21:54 UTC (permalink / raw)
To: Kevin Hilman
Cc: jean.pihet, linux-omap, santosh.shilimkar, linux-arm-kernel, Jean Pihet
On Wed, Jun 29, 2011 at 12:06:07PM -0700, Kevin Hilman wrote:
> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>
> > On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
> >> Russell, if you're OK with it, can you add it to your suspend branch for
> >> the upcoming merge window?
> >
> > Yes - though I think we can go a little bit further - this patch is on
> > top of my code so far, and is untested. There isn't a need for the
> > saving of these registers to be in assembly because we can read them
> > just as easily from C code.
>
> Indeed
>
> > Comments?
>
> Looks good to me (although untested) care to respin on top of $SUBJECT
> patch?
>
> Minor comments below...
Done.
arch/arm/mach-omap2/pm.h | 2 +-
arch/arm/mach-omap2/pm34xx.c | 19 ++++++++++++++++++-
arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index a4ec213..04ee566 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -97,7 +97,7 @@ extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
extern unsigned int omap24xx_cpu_suspend_sz;
/* 3xxx */
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void omap34xx_cpu_suspend(int save_state);
/* omap3_do_wfi function pointer and size, for copy to SRAM */
extern void omap3_do_wfi(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index e1c79ba..7238a63 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -306,9 +306,24 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void omap34xx_save_context(u32 *save)
+{
+ u32 val;
+
+ /* Read Auxiliary Control Register */
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+
+ /* Read L2 AUX ctrl register */
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- omap34xx_cpu_suspend(omap3_arm_context, save_state);
+ omap34xx_cpu_suspend(save_state);
}
void omap_sram_idle(void)
@@ -408,6 +423,8 @@ void omap_sram_idle(void)
* get saved. The rest is placed on the stack, and restored
* from there before resuming.
*/
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
if (save_state == 1 || save_state == 3)
cpu_suspend(save_state, omap34xx_do_sram_idle);
else
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 17dbc5a..f2ea1bd 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -152,8 +152,7 @@ ENTRY(omap34xx_cpu_suspend)
stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
@@ -166,19 +165,12 @@ ENTRY(omap34xx_cpu_suspend)
*/
ldr r4, omap3_do_wfi_sram_addr
ldr r5, [r4]
- cmp r1, #0x0 @ If no context save required,
+ cmp r0, #0x0 @ If no context save required,
bxeq r5 @ jump to the WFI code in SRAM
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
/*
* jump out to kernel flush routine
* - reuse that code is better
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 21:54 ` Russell King - ARM Linux
0 siblings, 0 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2011-06-29 21:54 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 29, 2011 at 12:06:07PM -0700, Kevin Hilman wrote:
> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>
> > On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
> >> Russell, if you're OK with it, can you add it to your suspend branch for
> >> the upcoming merge window?
> >
> > Yes - though I think we can go a little bit further - this patch is on
> > top of my code so far, and is untested. There isn't a need for the
> > saving of these registers to be in assembly because we can read them
> > just as easily from C code.
>
> Indeed
>
> > Comments?
>
> Looks good to me (although untested) care to respin on top of $SUBJECT
> patch?
>
> Minor comments below...
Done.
arch/arm/mach-omap2/pm.h | 2 +-
arch/arm/mach-omap2/pm34xx.c | 19 ++++++++++++++++++-
arch/arm/mach-omap2/sleep34xx.S | 12 ++----------
3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index a4ec213..04ee566 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -97,7 +97,7 @@ extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
extern unsigned int omap24xx_cpu_suspend_sz;
/* 3xxx */
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void omap34xx_cpu_suspend(int save_state);
/* omap3_do_wfi function pointer and size, for copy to SRAM */
extern void omap3_do_wfi(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index e1c79ba..7238a63 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -306,9 +306,24 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void omap34xx_save_context(u32 *save)
+{
+ u32 val;
+
+ /* Read Auxiliary Control Register */
+ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+
+ /* Read L2 AUX ctrl register */
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+ *save++ = 1;
+ *save++ = val;
+}
+
static void omap34xx_do_sram_idle(unsigned long save_state)
{
- omap34xx_cpu_suspend(omap3_arm_context, save_state);
+ omap34xx_cpu_suspend(save_state);
}
void omap_sram_idle(void)
@@ -408,6 +423,8 @@ void omap_sram_idle(void)
* get saved. The rest is placed on the stack, and restored
* from there before resuming.
*/
+ if (save_state)
+ omap34xx_save_context(omap3_arm_context);
if (save_state == 1 || save_state == 3)
cpu_suspend(save_state, omap34xx_do_sram_idle);
else
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 17dbc5a..f2ea1bd 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -152,8 +152,7 @@ ENTRY(omap34xx_cpu_suspend)
stmfd sp!, {r4 - r11, lr} @ save registers on stack
/*
- * r0 contains CPU context save/restore pointer in sdram
- * r1 contains information about saving context:
+ * r0 contains information about saving context:
* 0 - No context lost
* 1 - Only L1 and logic lost
* 2 - Only L2 lost (Even L1 is retained we clean it along with L2)
@@ -166,19 +165,12 @@ ENTRY(omap34xx_cpu_suspend)
*/
ldr r4, omap3_do_wfi_sram_addr
ldr r5, [r4]
- cmp r1, #0x0 @ If no context save required,
+ cmp r0, #0x0 @ If no context save required,
bxeq r5 @ jump to the WFI code in SRAM
/* Otherwise fall through to the save context code */
save_context_wfi:
- mov r8, r0 @ Store SDRAM address in r8
- mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
- mov r4, #0x1 @ Number of parameters for restore call
- stmia r8!, {r4-r5} @ Push parameters for restore call
- mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
- stmia r8!, {r4-r5} @ Push parameters for restore call
-
/*
* jump out to kernel flush routine
* - reuse that code is better
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 21:54 ` Russell King - ARM Linux
@ 2011-06-29 23:30 ` Kevin Hilman
-1 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 23:30 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: jean.pihet, linux-omap, santosh.shilimkar, linux-arm-kernel, Jean Pihet
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
> On Wed, Jun 29, 2011 at 12:06:07PM -0700, Kevin Hilman wrote:
>> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>>
>> > On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
>> >> Russell, if you're OK with it, can you add it to your suspend branch for
>> >> the upcoming merge window?
>> >
>> > Yes - though I think we can go a little bit further - this patch is on
>> > top of my code so far, and is untested. There isn't a need for the
>> > saving of these registers to be in assembly because we can read them
>> > just as easily from C code.
>>
>> Indeed
>>
>> > Comments?
>>
>> Looks good to me (although untested) care to respin on top of $SUBJECT
>> patch?
>>
>> Minor comments below...
>
> Done.
Tested-by: Kevin Hilman <khilman@ti.com>
Tested full-chip retention and off on 3430/n900, 3530/Overo and
3630/Zoom3.
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-29 23:30 ` Kevin Hilman
0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-29 23:30 UTC (permalink / raw)
To: linux-arm-kernel
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
> On Wed, Jun 29, 2011 at 12:06:07PM -0700, Kevin Hilman wrote:
>> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>>
>> > On Wed, Jun 29, 2011 at 10:29:49AM -0700, Kevin Hilman wrote:
>> >> Russell, if you're OK with it, can you add it to your suspend branch for
>> >> the upcoming merge window?
>> >
>> > Yes - though I think we can go a little bit further - this patch is on
>> > top of my code so far, and is untested. There isn't a need for the
>> > saving of these registers to be in assembly because we can read them
>> > just as easily from C code.
>>
>> Indeed
>>
>> > Comments?
>>
>> Looks good to me (although untested) care to respin on top of $SUBJECT
>> patch?
>>
>> Minor comments below...
>
> Done.
Tested-by: Kevin Hilman <khilman@ti.com>
Tested full-chip retention and off on 3430/n900, 3530/Overo and
3630/Zoom3.
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 16:40 ` jean.pihet at newoldbits.com
` (2 preceding siblings ...)
(?)
@ 2011-06-30 8:55 ` Peter De Schrijver
-1 siblings, 0 replies; 26+ messages in thread
From: Peter De Schrijver @ 2011-06-30 8:55 UTC (permalink / raw)
To: jean.pihet
Cc: khilman, linux-omap, santosh.shilimkar, Russell King,
linux-arm-kernel, Jean Pihet
> +/*
> + * This function implements the erratum ID i581 WA:
> + * SDRC state restore before accessing the SDRAM
> + *
> + * Only used at return from non-OFF mode. For OFF
> + * mode the ROM code configures the SDRC and
> + * the DPLL before calling the restore code directly
> + * from DDR.
> + */
> +
> +/* Make sure SDRC accesses are ok */
> +wait_sdrc_ok:
> +
> +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
> + ldr r4, cm_idlest_ckgen
> +wait_dpll3_lock:
> + ldr r5, [r4]
> + tst r5, #1
> + beq wait_dpll3_lock
> +
> + ldr r4, cm_idlest1_core
> +wait_sdrc_ready:
> + ldr r5, [r4]
> + tst r5, #0x2
> + bne wait_sdrc_ready
> + /* allow DLL powerdown upon hw idle req */
> + ldr r4, sdrc_power
> + ldr r5, [r4]
> + bic r5, r5, #0x40
> + str r5, [r4]
> +
> +/*
> + * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
> + * base instead.
> + * Be careful not to clobber r7 when maintaing this code.
> + */
> +
> +is_dll_in_lock_mode:
> + /* Is dll in lock mode? */
> + ldr r4, sdrc_dlla_ctrl
> + ldr r5, [r4]
> + tst r5, #0x4
> + bne exit_nonoff_modes @ Return if locked
> + /* wait till dll locks */
> + adr r7, kick_counter
> +wait_dll_lock_timed:
> + ldr r4, wait_dll_lock_counter
> + add r4, r4, #1
> + str r4, [r7, #wait_dll_lock_counter - kick_counter]
> + ldr r4, sdrc_dlla_status
> + /* Wait 20uS for lock */
> + mov r6, #8
This was once calibrated using a scope on 3430 running from uncached
SRAM, maybe this needs to verified for 3630 or other newer OMAP3 variants.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-29 16:40 ` jean.pihet at newoldbits.com
@ 2011-07-12 6:07 ` Pavel Machek
-1 siblings, 0 replies; 26+ messages in thread
From: Pavel Machek @ 2011-07-12 6:07 UTC (permalink / raw)
To: jean.pihet
Cc: khilman, santosh.shilimkar, Russell King, linux-omap, Jean Pihet,
linux-arm-kernel
On Wed 2011-06-29 18:40:23, jean.pihet@newoldbits.com wrote:
> From: Jean Pihet <j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage and the overhead in the code copy.
So... what do you plan to use sram for? Because I don't think the
speedup is worth the complexity...
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-07-12 6:07 ` Pavel Machek
0 siblings, 0 replies; 26+ messages in thread
From: Pavel Machek @ 2011-07-12 6:07 UTC (permalink / raw)
To: linux-arm-kernel
On Wed 2011-06-29 18:40:23, jean.pihet at newoldbits.com wrote:
> From: Jean Pihet <j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage and the overhead in the code copy.
So... what do you plan to use sram for? Because I don't think the
speedup is worth the complexity...
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-07-12 6:07 ` Pavel Machek
@ 2011-07-13 8:14 ` Paul Walmsley
-1 siblings, 0 replies; 26+ messages in thread
From: Paul Walmsley @ 2011-07-13 8:14 UTC (permalink / raw)
To: Pavel Machek
Cc: jean.pihet, khilman, linux-omap, santosh.shilimkar, Russell King,
linux-arm-kernel, Jean Pihet
On Tue, 12 Jul 2011, Pavel Machek wrote:
> On Wed 2011-06-29 18:40:23, jean.pihet@newoldbits.com wrote:
> > From: Jean Pihet <j-pihet@ti.com>
> >
> > Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> > is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> > However only a small part of the code really needs to run from internal SRAM.
> >
> > This fix lets most of the ASM idle code run from the DDR
> > in order to minimize the SRAM usage and the overhead in the code copy.
>
> So... what do you plan to use sram for? Because I don't think the
> speedup is worth the complexity...
The SDRAM may not be accessible yet when the chip isn't waking up from
off-mode, so SRAM is the only option. The comments & code in the patch
surrounding the "wait_sdrc_ok" label refer to this issue - albeit, perhaps
telegraphically.
- Paul
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-07-13 8:14 ` Paul Walmsley
0 siblings, 0 replies; 26+ messages in thread
From: Paul Walmsley @ 2011-07-13 8:14 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 12 Jul 2011, Pavel Machek wrote:
> On Wed 2011-06-29 18:40:23, jean.pihet at newoldbits.com wrote:
> > From: Jean Pihet <j-pihet@ti.com>
> >
> > Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> > is copied to internal SRAM at boot and after wake-up from CORE OFF mode.
> > However only a small part of the code really needs to run from internal SRAM.
> >
> > This fix lets most of the ASM idle code run from the DDR
> > in order to minimize the SRAM usage and the overhead in the code copy.
>
> So... what do you plan to use sram for? Because I don't think the
> speedup is worth the complexity...
The SDRAM may not be accessible yet when the chip isn't waking up from
off-mode, so SRAM is the only option. The comments & code in the patch
surrounding the "wait_sdrc_ok" label refer to this issue - albeit, perhaps
telegraphically.
- Paul
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-24 8:32 ` Jean Pihet
@ 2011-06-24 14:42 ` Kevin Hilman
0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2011-06-24 14:42 UTC (permalink / raw)
To: Jean Pihet; +Cc: linux-omap, santosh.shilimkar
Jean Pihet <jean.pihet@newoldbits.com> writes:
> Hi Kevin,
>
> On Fri, Jun 24, 2011 at 2:17 AM, Kevin Hilman <khilman@ti.com> wrote:
>> Hi Jean,
>>
>> Can you rebase/retest this on top of my pm-wip/idle-suspend branch,
>> which now contains Russell's major cleanup to use the common code as
>> well as an additional patch from me to remove the unncessary
>> get_*_restore_pointer functions:
>>
>> [PATCH] OMAP3: PM: remove get_*_restore_pointer functions, directly use entry points
>
> Sure I will rebase on your pm-wip/idle-suspend branch,
Thanks.
> with the
> ENDPROC fix as well as the v7_processor_functions patch applied.
Russell already has those fixed in his branch, so my pm-wip/idle-suspend
already includes these.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-24 0:17 ` Kevin Hilman
@ 2011-06-24 8:32 ` Jean Pihet
2011-06-24 14:42 ` Kevin Hilman
0 siblings, 1 reply; 26+ messages in thread
From: Jean Pihet @ 2011-06-24 8:32 UTC (permalink / raw)
To: Kevin Hilman; +Cc: linux-omap, santosh.shilimkar
Hi Kevin,
On Fri, Jun 24, 2011 at 2:17 AM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Jean,
>
> Can you rebase/retest this on top of my pm-wip/idle-suspend branch,
> which now contains Russell's major cleanup to use the common code as
> well as an additional patch from me to remove the unncessary
> get_*_restore_pointer functions:
>
> [PATCH] OMAP3: PM: remove get_*_restore_pointer functions, directly use entry points
Sure I will rebase on your pm-wip/idle-suspend branch, with the
ENDPROC fix as well as the v7_processor_functions patch applied.
>
> Thanks,
>
> Kevin
Regards,
Jean
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-17 8:52 jean.pihet
2011-06-17 9:51 ` Santosh Shilimkar
@ 2011-06-24 0:17 ` Kevin Hilman
2011-06-24 8:32 ` Jean Pihet
1 sibling, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2011-06-24 0:17 UTC (permalink / raw)
To: jean.pihet; +Cc: linux-omap, santosh.shilimkar, Jean Pihet
jean.pihet@newoldbits.com writes:
> From: Jean Pihet <j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM and run from there.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage. No performance
> loss or gain can be measured with a 32KHz clock period.
>
> The only pieces of code that are mandatory in SRAM
> are:
> - the i443 erratum WA,
> - the i581 erratum WA,
> - the security extension code.
>
> SRAM usage:
> - original code:
> . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
> . 1196 bytes for omap_sram_idle (used by suspend/resume in RETention),
> . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
> . 108 bytes for save_secure_ram_context (used on HS parts only).
>
> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
> so the gain in SRAM usage for suspend/resume is 908 bytes.
>
> Also fixed the SRAM initialization sequence to avoid an unnecessary
> copy to SRAM at boot time and for readability.
>
> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
Hi Jean,
Can you rebase/retest this on top of my pm-wip/idle-suspend branch,
which now contains Russell's major cleanup to use the common code as
well as an additional patch from me to remove the unncessary
get_*_restore_pointer functions:
[PATCH] OMAP3: PM: remove get_*_restore_pointer functions, directly use entry points
Thanks,
Kevin
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH] OMAP3: run the ASM sleep code from DDR
2011-06-17 8:52 jean.pihet
@ 2011-06-17 9:51 ` Santosh Shilimkar
2011-06-24 0:17 ` Kevin Hilman
1 sibling, 0 replies; 26+ messages in thread
From: Santosh Shilimkar @ 2011-06-17 9:51 UTC (permalink / raw)
To: jean.pihet; +Cc: linux-omap, Jean Pihet
On 6/17/2011 2:22 PM, jean.pihet@newoldbits.com wrote:
> From: Jean Pihet<j-pihet@ti.com>
>
> Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
> is copied to internal SRAM and run from there.
> However only a small part of the code really needs to run from internal SRAM.
>
> This fix lets most of the ASM idle code run from the DDR
> in order to minimize the SRAM usage. No performance
> loss or gain can be measured with a 32KHz clock period.
>
> The only pieces of code that are mandatory in SRAM
> are:
> - the i443 erratum WA,
> - the i581 erratum WA,
> - the security extension code.
>
> SRAM usage:
> - original code:
> . 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
> . 1196 bytes for omap_sram_idle (used by suspend/resume in RETention),
> . 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
> . 108 bytes for save_secure_ram_context (used on HS parts only).
>
> With this fix the usage for suspend/resume in RETention goes down 288 bytes,
> so the gain in SRAM usage for suspend/resume is 908 bytes.
>
> Also fixed the SRAM initialization sequence to avoid an unnecessary
> copy to SRAM at boot time and for readability.
>
> Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet<j-pihet@ti.com>
As mentioned in the other thread, with auto-deps set always
which is the case on OMAP3, this patch is safe.
FWIW: Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>c
> ---
> arch/arm/mach-omap2/pm.h | 20 ++-
> arch/arm/mach-omap2/pm34xx.c | 20 ++-
> arch/arm/mach-omap2/sleep34xx.S | 316 ++++++++++++++++++++++-----------------
> arch/arm/plat-omap/sram.c | 15 +--
> 4 files changed, 213 insertions(+), 158 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 45bcfce..a4ec213 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);
> #define pm_dbg_regset_init(reg_set) do {} while (0);
> #endif /* CONFIG_PM_DEBUG */
>
> +/* 24xx */
> extern void omap24xx_idle_loop_suspend(void);
> +extern unsigned int omap24xx_idle_loop_suspend_sz;
>
> extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
> void __iomem *sdrc_power);
> +extern unsigned int omap24xx_cpu_suspend_sz;
> +
> +/* 3xxx */
> extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
> -extern int save_secure_ram_context(u32 *addr);
> -extern void omap3_save_scratchpad_contents(void);
>
> -extern unsigned int omap24xx_idle_loop_suspend_sz;
> +/* omap3_do_wfi function pointer and size, for copy to SRAM */
> +extern void omap3_do_wfi(void);
> +extern unsigned int omap3_do_wfi_sz;
> +/* ... and its pointer from SRAM after copy */
> +extern void (*omap3_do_wfi_sram)(void);
> +
> +/* save_secure_ram_context function pointer and size, for copy to SRAM */
> +extern int save_secure_ram_context(u32 *addr);
> extern unsigned int save_secure_ram_context_sz;
> -extern unsigned int omap24xx_cpu_suspend_sz;
> -extern unsigned int omap34xx_cpu_suspend_sz;
> +
> +extern void omap3_save_scratchpad_contents(void);
>
> #define PM_RTA_ERRATUM_i608 (1<< 0)
> #define PM_SDRC_WAKEUP_ERRATUM_i583 (1<< 1)
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index c155c9d..f056732 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -83,9 +83,8 @@ struct power_state {
>
> static LIST_HEAD(pwrst_list);
>
> -static void (*_omap_sram_idle)(u32 *addr, int save_state);
> -
> static int (*_omap_save_secure_sram)(u32 *addr);
> +void (*omap3_do_wfi_sram)(void);
>
> static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
> static struct powerdomain *core_pwrdm, *per_pwrdm;
> @@ -352,9 +351,6 @@ void omap_sram_idle(void)
> int core_prev_state, per_prev_state;
> u32 sdrc_pwr = 0;
>
> - if (!_omap_sram_idle)
> - return;
> -
> pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
> pwrdm_clear_all_prev_pwrst(neon_pwrdm);
> pwrdm_clear_all_prev_pwrst(core_pwrdm);
> @@ -436,7 +432,7 @@ void omap_sram_idle(void)
> * get saved. The restore path then reads from this
> * location and restores them back.
> */
> - _omap_sram_idle(omap3_arm_context, save_state);
> + omap34xx_cpu_suspend(omap3_arm_context, save_state);
> cpu_init();
>
> /* Restore normal SDRC POWER settings */
> @@ -852,10 +848,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
> return 0;
> }
>
> +/*
> + * Push functions to SRAM
> + *
> + * The minimum set of functions is pushed to SRAM for execution:
> + * - omap3_do_wfi for erratum i581 WA,
> + * - save_secure_ram_context for security extensions.
> + */
> void omap_push_sram_idle(void)
> {
> - _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
> - omap34xx_cpu_suspend_sz);
> + omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
> +
> if (omap_type() != OMAP2_DEVICE_TYPE_GP)
> _omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
> save_secure_ram_context_sz);
> @@ -920,7 +923,6 @@ static int __init omap3_pm_init(void)
> per_clkdm = clkdm_lookup("per_clkdm");
> core_clkdm = clkdm_lookup("core_clkdm");
>
> - omap_push_sram_idle();
> #ifdef CONFIG_SUSPEND
> suspend_set_ops(&omap_pm_ops);
> #endif /* CONFIG_SUSPEND */
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
> index 63f1066..2ef0c0d 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -179,8 +179,10 @@ ENTRY(save_secure_ram_context_sz)
> *
> *
> * Notes:
> - * - this code gets copied to internal SRAM at boot and after wake-up
> - * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
> + * - only the minimum set of functions gets copied to internal SRAM at boot
> + * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
> + * pointers in SDRAM or SRAM are called depending on the desired low power
> + * target state.
> * - when the OMAP wakes up it continues at different execution points
> * depending on the low power mode (non-OFF vs OFF modes),
> * cf. 'Resume path for xxx mode' comments.
> @@ -198,9 +200,15 @@ ENTRY(omap34xx_cpu_suspend)
> * 3 - Both L1 and L2 lost and logic lost
> */
>
> - /* Directly jump to WFI is the context save is not required */
> - cmp r1, #0x0
> - beq omap3_do_wfi
> + /*
> + * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
> + * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
> + */
> + ldr r4, omap3_do_wfi_sram_addr
> + ldr r5, [r4]
> + cmp r1, #0x0 @ If no context save required,
> + bxeq r5 @ jump to the WFI code in SRAM
> +
>
> /* Otherwise fall through to the save context code */
> save_context_wfi:
> @@ -284,7 +292,32 @@ clean_caches:
> THUMB( nop )
> .arm
>
> -omap3_do_wfi:
> + b omap3_do_wfi
> +
> +/*
> + * Local variables
> + */
> +omap3_do_wfi_sram_addr:
> + .word omap3_do_wfi_sram
> +kernel_flush:
> + .word v7_flush_dcache_all
> +
> +/* ===================================
> + * == WFI instruction => Enter idle ==
> + * ===================================
> + */
> +
> +/*
> + * Do WFI instruction
> + * Includes the resume path for non-OFF modes
> + *
> + * This code gets copied to internal SRAM and is accessible
> + * from both SDRAM and SRAM:
> + * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
> + * - executed from SDRAM for OFF mode (omap3_do_wfi).
> + */
> + .align 3
> +ENTRY(omap3_do_wfi)
> ldr r4, sdrc_power @ read the SDRC_POWER register
> ldr r5, [r4] @ read the contents of SDRC_POWER
> orr r5, r5, #0x40 @ enable self refresh on idle req
> @@ -316,8 +349,86 @@ omap3_do_wfi:
> nop
> nop
> nop
> - bl wait_sdrc_ok
>
> +/*
> + * This function implements the erratum ID i581 WA:
> + * SDRC state restore before accessing the SDRAM
> + *
> + * Only used at return from non-OFF mode. For OFF
> + * mode the ROM code configures the SDRC and
> + * the DPLL before calling the restore code directly
> + * from DDR.
> + */
> +
> +/* Make sure SDRC accesses are ok */
> +wait_sdrc_ok:
> +
> +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
> + ldr r4, cm_idlest_ckgen
> +wait_dpll3_lock:
> + ldr r5, [r4]
> + tst r5, #1
> + beq wait_dpll3_lock
> +
> + ldr r4, cm_idlest1_core
> +wait_sdrc_ready:
> + ldr r5, [r4]
> + tst r5, #0x2
> + bne wait_sdrc_ready
> + /* allow DLL powerdown upon hw idle req */
> + ldr r4, sdrc_power
> + ldr r5, [r4]
> + bic r5, r5, #0x40
> + str r5, [r4]
> +
> +/*
> + * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
> + * base instead.
> + * Be careful not to clobber r7 when maintaing this code.
> + */
> +
> +is_dll_in_lock_mode:
> + /* Is dll in lock mode? */
> + ldr r4, sdrc_dlla_ctrl
> + ldr r5, [r4]
> + tst r5, #0x4
> + bne exit_nonoff_modes @ Return if locked
> + /* wait till dll locks */
> + adr r7, kick_counter
> +wait_dll_lock_timed:
> + ldr r4, wait_dll_lock_counter
> + add r4, r4, #1
> + str r4, [r7, #wait_dll_lock_counter - kick_counter]
> + ldr r4, sdrc_dlla_status
> + /* Wait 20uS for lock */
> + mov r6, #8
> +wait_dll_lock:
> + subs r6, r6, #0x1
> + beq kick_dll
> + ldr r5, [r4]
> + and r5, r5, #0x4
> + cmp r5, #0x4
> + bne wait_dll_lock
> + b exit_nonoff_modes @ Return when locked
> +
> + /* disable/reenable DLL if not locked */
> +kick_dll:
> + ldr r4, sdrc_dlla_ctrl
> + ldr r5, [r4]
> + mov r6, r5
> + bic r6, #(1<<3) @ disable dll
> + str r6, [r4]
> + dsb
> + orr r6, r6, #(1<<3) @ enable dll
> + str r6, [r4]
> + dsb
> + ldr r4, kick_counter
> + add r4, r4, #1
> + str r4, [r7] @ kick_counter
> + b wait_dll_lock_timed
> +
> +exit_nonoff_modes:
> + /* Re-enable C-bit if needed */
> mrc p15, 0, r0, c1, c0, 0
> tst r0, #(1<< 2) @ Check C bit enabled?
> orreq r0, r0, #(1<< 2) @ Enable the C bit if cleared
> @@ -331,6 +442,31 @@ omap3_do_wfi:
> */
> ldmfd sp!, {r0-r12, pc} @ restore regs and return
>
> +/*
> + * Local variables
> + */
> +sdrc_power:
> + .word SDRC_POWER_V
> +cm_idlest1_core:
> + .word CM_IDLEST1_CORE_V
> +cm_idlest_ckgen:
> + .word CM_IDLEST_CKGEN_V
> +sdrc_dlla_status:
> + .word SDRC_DLLA_STATUS_V
> +sdrc_dlla_ctrl:
> + .word SDRC_DLLA_CTRL_V
> + /*
> + * When exporting to userspace while the counters are in SRAM,
> + * these 2 words need to be at the end to facilitate retrival!
> + */
> +kick_counter:
> + .word 0
> +wait_dll_lock_counter:
> + .word 0
> +
> +ENTRY(omap3_do_wfi_sz)
> + .word . - omap3_do_wfi
> +
>
> /*
> * ==============================
> @@ -346,6 +482,10 @@ omap3_do_wfi:
> * restore_es3: applies to 34xx>= ES3.0
> * restore_3630: applies to 36xx
> * restore: common code for 3xxx
> + *
> + * Note: when back from CORE and MPU OFF mode we are running
> + * from SDRAM, without MMU, without the caches and prediction.
> + * Also the SRAM content has been cleared.
> */
> restore_es3:
> ldr r5, pm_prepwstst_core_p
> @@ -364,7 +504,8 @@ copy_to_sram:
> bne copy_to_sram
> ldr r1, sram_base
> blx r1
> - b restore
> +
> + b restore @ Fall through to common code
>
> restore_3630:
> ldr r1, pm_prepwstst_core_p
> @@ -574,12 +715,41 @@ usettbr0:
> restoremmu_on:
> ldmfd sp!, {r0-r12, pc} @ restore regs and return
>
> +/*
> + * Local variables
> + */
> +pm_prepwstst_core_p:
> + .word PM_PREPWSTST_CORE_P
> +pm_pwstctrl_mpu:
> + .word PM_PWSTCTRL_MPU_P
> +scratchpad_base:
> + .word SCRATCHPAD_BASE_P
> +sram_base:
> + .word SRAM_BASE_P + 0x8000
> +ttbrbit_mask:
> + .word 0xFFFFC000
> +table_index_mask:
> + .word 0xFFF00000
> +table_entry:
> + .word 0x00000C02
> +cache_pred_disable_mask:
> + .word 0xFFFFE7FB
> +control_stat:
> + .word CONTROL_STAT
> +control_mem_rta:
> + .word CONTROL_MEM_RTA_CTRL
> +l2dis_3630:
> + .word 0
> +
>
> /*
> * Internal functions
> */
>
> -/* This function implements the erratum ID i443 WA, applies to 34xx>= ES3.0 */
> +/* This function implements the erratum ID i443 WA, applies to 34xx>= ES3.0
> + *
> + * Copied and run from SRAM in order to reconfigure the SDRC parameters.
> + */
> .text
> .align 3
> ENTRY(es3_sdrc_fix)
> @@ -609,6 +779,9 @@ ENTRY(es3_sdrc_fix)
> str r5, [r4] @ kick off refreshes
> bx lr
>
> +/*
> + * Local variables
> + */
> .align
> sdrc_syscfg:
> .word SDRC_SYSCONFIG_P
> @@ -627,128 +800,3 @@ sdrc_manual_1:
> ENDPROC(es3_sdrc_fix)
> ENTRY(es3_sdrc_fix_sz)
> .word . - es3_sdrc_fix
> -
> -/*
> - * This function implements the erratum ID i581 WA:
> - * SDRC state restore before accessing the SDRAM
> - *
> - * Only used at return from non-OFF mode. For OFF
> - * mode the ROM code configures the SDRC and
> - * the DPLL before calling the restore code directly
> - * from DDR.
> - */
> -
> -/* Make sure SDRC accesses are ok */
> -wait_sdrc_ok:
> -
> -/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
> - ldr r4, cm_idlest_ckgen
> -wait_dpll3_lock:
> - ldr r5, [r4]
> - tst r5, #1
> - beq wait_dpll3_lock
> -
> - ldr r4, cm_idlest1_core
> -wait_sdrc_ready:
> - ldr r5, [r4]
> - tst r5, #0x2
> - bne wait_sdrc_ready
> - /* allow DLL powerdown upon hw idle req */
> - ldr r4, sdrc_power
> - ldr r5, [r4]
> - bic r5, r5, #0x40
> - str r5, [r4]
> -
> -/*
> - * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
> - * base instead.
> - * Be careful not to clobber r7 when maintaing this code.
> - */
> -
> -is_dll_in_lock_mode:
> - /* Is dll in lock mode? */
> - ldr r4, sdrc_dlla_ctrl
> - ldr r5, [r4]
> - tst r5, #0x4
> - bxne lr @ Return if locked
> - /* wait till dll locks */
> - adr r7, kick_counter
> -wait_dll_lock_timed:
> - ldr r4, wait_dll_lock_counter
> - add r4, r4, #1
> - str r4, [r7, #wait_dll_lock_counter - kick_counter]
> - ldr r4, sdrc_dlla_status
> - /* Wait 20uS for lock */
> - mov r6, #8
> -wait_dll_lock:
> - subs r6, r6, #0x1
> - beq kick_dll
> - ldr r5, [r4]
> - and r5, r5, #0x4
> - cmp r5, #0x4
> - bne wait_dll_lock
> - bx lr @ Return when locked
> -
> - /* disable/reenable DLL if not locked */
> -kick_dll:
> - ldr r4, sdrc_dlla_ctrl
> - ldr r5, [r4]
> - mov r6, r5
> - bic r6, #(1<<3) @ disable dll
> - str r6, [r4]
> - dsb
> - orr r6, r6, #(1<<3) @ enable dll
> - str r6, [r4]
> - dsb
> - ldr r4, kick_counter
> - add r4, r4, #1
> - str r4, [r7] @ kick_counter
> - b wait_dll_lock_timed
> -
> - .align
> -cm_idlest1_core:
> - .word CM_IDLEST1_CORE_V
> -cm_idlest_ckgen:
> - .word CM_IDLEST_CKGEN_V
> -sdrc_dlla_status:
> - .word SDRC_DLLA_STATUS_V
> -sdrc_dlla_ctrl:
> - .word SDRC_DLLA_CTRL_V
> -pm_prepwstst_core_p:
> - .word PM_PREPWSTST_CORE_P
> -pm_pwstctrl_mpu:
> - .word PM_PWSTCTRL_MPU_P
> -scratchpad_base:
> - .word SCRATCHPAD_BASE_P
> -sram_base:
> - .word SRAM_BASE_P + 0x8000
> -sdrc_power:
> - .word SDRC_POWER_V
> -ttbrbit_mask:
> - .word 0xFFFFC000
> -table_index_mask:
> - .word 0xFFF00000
> -table_entry:
> - .word 0x00000C02
> -cache_pred_disable_mask:
> - .word 0xFFFFE7FB
> -control_stat:
> - .word CONTROL_STAT
> -control_mem_rta:
> - .word CONTROL_MEM_RTA_CTRL
> -kernel_flush:
> - .word v7_flush_dcache_all
> -l2dis_3630:
> - .word 0
> - /*
> - * When exporting to userspace while the counters are in SRAM,
> - * these 2 words need to be at the end to facilitate retrival!
> - */
> -kick_counter:
> - .word 0
> -wait_dll_lock_counter:
> - .word 0
> -ENDPROC(omap34xx_cpu_suspend)
> -
> -ENTRY(omap34xx_cpu_suspend_sz)
> - .word . - omap34xx_cpu_suspend
> diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
> index 6af3d0b..363c91e 100644
> --- a/arch/arm/plat-omap/sram.c
> +++ b/arch/arm/plat-omap/sram.c
> @@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
> }
> #endif /* CONFIG_PM */
>
> -static int __init omap34xx_sram_init(void)
> -{
> - _omap3_sram_configure_core_dpll =
> - omap_sram_push(omap3_sram_configure_core_dpll,
> - omap3_sram_configure_core_dpll_sz);
> - omap_push_sram_idle();
> - return 0;
> -}
> -#else
> +#endif /* CONFIG_ARCH_OMAP3 */
> +
> static inline int omap34xx_sram_init(void)
> {
> +#if defined(CONFIG_ARCH_OMAP3)&& defined(CONFIG_PM)
> + omap3_sram_restore_context();
> +#endif
> return 0;
> }
> -#endif
>
> int __init omap_sram_init(void)
> {
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-06-17 8:52 jean.pihet
2011-06-17 9:51 ` Santosh Shilimkar
2011-06-24 0:17 ` Kevin Hilman
0 siblings, 2 replies; 26+ messages in thread
From: jean.pihet @ 2011-06-17 8:52 UTC (permalink / raw)
To: linux-omap, santosh.shilimkar; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Most of the ASM sleep code (in arch/arm/mach-omap2/sleep34xx.S)
is copied to internal SRAM and run from there.
However only a small part of the code really needs to run from internal SRAM.
This fix lets most of the ASM idle code run from the DDR
in order to minimize the SRAM usage. No performance
loss or gain can be measured with a 32KHz clock period.
The only pieces of code that are mandatory in SRAM
are:
- the i443 erratum WA,
- the i581 erratum WA,
- the security extension code.
SRAM usage:
- original code:
. 560 bytes for omap3_sram_configure_core_dpll (used by DVFS),
. 1196 bytes for omap_sram_idle (used by suspend/resume in RETention),
. 124 bytes for es3_sdrc_fix (used by suspend/resume in OFF mode on ES3.x),
. 108 bytes for save_secure_ram_context (used on HS parts only).
With this fix the usage for suspend/resume in RETention goes down 288 bytes,
so the gain in SRAM usage for suspend/resume is 908 bytes.
Also fixed the SRAM initialization sequence to avoid an unnecessary
copy to SRAM at boot time and for readability.
Tested on Beagleboard (ES2.x) in idle with full RET and OFF modes.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/pm.h | 20 ++-
arch/arm/mach-omap2/pm34xx.c | 20 ++-
arch/arm/mach-omap2/sleep34xx.S | 316 ++++++++++++++++++++++-----------------
arch/arm/plat-omap/sram.c | 15 +--
4 files changed, 213 insertions(+), 158 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..a4ec213 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);
#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
+/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
+extern unsigned int omap24xx_cpu_suspend_sz;
+
+/* 3xxx */
extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
#define PM_RTA_ERRATUM_i608 (1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d..f056732 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -83,9 +83,8 @@ struct power_state {
static LIST_HEAD(pwrst_list);
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -352,9 +351,6 @@ void omap_sram_idle(void)
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
- if (!_omap_sram_idle)
- return;
-
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
pwrdm_clear_all_prev_pwrst(neon_pwrdm);
pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -436,7 +432,7 @@ void omap_sram_idle(void)
* get saved. The restore path then reads from this
* location and restores them back.
*/
- _omap_sram_idle(omap3_arm_context, save_state);
+ omap34xx_cpu_suspend(omap3_arm_context, save_state);
cpu_init();
/* Restore normal SDRC POWER settings */
@@ -852,10 +848,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
void omap_push_sram_idle(void)
{
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
@@ -920,7 +923,6 @@ static int __init omap3_pm_init(void)
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
- omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 63f1066..2ef0c0d 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -179,8 +179,10 @@ ENTRY(save_secure_ram_context_sz)
*
*
* Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- * from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ * and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ * pointers in SDRAM or SRAM are called depending on the desired low power
+ * target state.
* - when the OMAP wakes up it continues at different execution points
* depending on the low power mode (non-OFF vs OFF modes),
* cf. 'Resume path for xxx mode' comments.
@@ -198,9 +200,15 @@ ENTRY(omap34xx_cpu_suspend)
* 3 - Both L1 and L2 lost and logic lost
*/
- /* Directly jump to WFI is the context save is not required */
- cmp r1, #0x0
- beq omap3_do_wfi
+ /*
+ * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+ * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+ */
+ ldr r4, omap3_do_wfi_sram_addr
+ ldr r5, [r4]
+ cmp r1, #0x0 @ If no context save required,
+ bxeq r5 @ jump to the WFI code in SRAM
+
/* Otherwise fall through to the save context code */
save_context_wfi:
@@ -284,7 +292,32 @@ clean_caches:
THUMB( nop )
.arm
-omap3_do_wfi:
+ b omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+ .word omap3_do_wfi_sram
+kernel_flush:
+ .word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+ .align 3
+ENTRY(omap3_do_wfi)
ldr r4, sdrc_power @ read the SDRC_POWER register
ldr r5, [r4] @ read the contents of SDRC_POWER
orr r5, r5, #0x40 @ enable self refresh on idle req
@@ -316,8 +349,86 @@ omap3_do_wfi:
nop
nop
nop
- bl wait_sdrc_ok
+/*
+ * This function implements the erratum ID i581 WA:
+ * SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+ ldr r4, cm_idlest_ckgen
+wait_dpll3_lock:
+ ldr r5, [r4]
+ tst r5, #1
+ beq wait_dpll3_lock
+
+ ldr r4, cm_idlest1_core
+wait_sdrc_ready:
+ ldr r5, [r4]
+ tst r5, #0x2
+ bne wait_sdrc_ready
+ /* allow DLL powerdown upon hw idle req */
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+ adr r7, kick_counter
+wait_dll_lock_timed:
+ ldr r4, wait_dll_lock_counter
+ add r4, r4, #1
+ str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+wait_dll_lock:
+ subs r6, r6, #0x1
+ beq kick_dll
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ b exit_nonoff_modes @ Return when locked
+
+ /* disable/reenable DLL if not locked */
+kick_dll:
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ mov r6, r5
+ bic r6, #(1<<3) @ disable dll
+ str r6, [r4]
+ dsb
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+ ldr r4, kick_counter
+ add r4, r4, #1
+ str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+exit_nonoff_modes:
+ /* Re-enable C-bit if needed */
mrc p15, 0, r0, c1, c0, 0
tst r0, #(1 << 2) @ Check C bit enabled?
orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
@@ -331,6 +442,31 @@ omap3_do_wfi:
*/
ldmfd sp!, {r0-r12, pc} @ restore regs and return
+/*
+ * Local variables
+ */
+sdrc_power:
+ .word SDRC_POWER_V
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+ .word CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+ /*
+ * When exporting to userspace while the counters are in SRAM,
+ * these 2 words need to be at the end to facilitate retrival!
+ */
+kick_counter:
+ .word 0
+wait_dll_lock_counter:
+ .word 0
+
+ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
+
/*
* ==============================
@@ -346,6 +482,10 @@ omap3_do_wfi:
* restore_es3: applies to 34xx >= ES3.0
* restore_3630: applies to 36xx
* restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ * from SDRAM, without MMU, without the caches and prediction.
+ * Also the SRAM content has been cleared.
*/
restore_es3:
ldr r5, pm_prepwstst_core_p
@@ -364,7 +504,8 @@ copy_to_sram:
bne copy_to_sram
ldr r1, sram_base
blx r1
- b restore
+
+ b restore @ Fall through to common code
restore_3630:
ldr r1, pm_prepwstst_core_p
@@ -574,12 +715,41 @@ usettbr0:
restoremmu_on:
ldmfd sp!, {r0-r12, pc} @ restore regs and return
+/*
+ * Local variables
+ */
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+ .word PM_PWSTCTRL_MPU_P
+scratchpad_base:
+ .word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
+ttbrbit_mask:
+ .word 0xFFFFC000
+table_index_mask:
+ .word 0xFFF00000
+table_entry:
+ .word 0x00000C02
+cache_pred_disable_mask:
+ .word 0xFFFFE7FB
+control_stat:
+ .word CONTROL_STAT
+control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+ .word 0
+
/*
* Internal functions
*/
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ *
+ * Copied and run from SRAM in order to reconfigure the SDRC parameters.
+ */
.text
.align 3
ENTRY(es3_sdrc_fix)
@@ -609,6 +779,9 @@ ENTRY(es3_sdrc_fix)
str r5, [r4] @ kick off refreshes
bx lr
+/*
+ * Local variables
+ */
.align
sdrc_syscfg:
.word SDRC_SYSCONFIG_P
@@ -627,128 +800,3 @@ sdrc_manual_1:
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
.word . - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- * SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
- ldr r4, cm_idlest_ckgen
-wait_dpll3_lock:
- ldr r5, [r4]
- tst r5, #1
- beq wait_dpll3_lock
-
- ldr r4, cm_idlest1_core
-wait_sdrc_ready:
- ldr r5, [r4]
- tst r5, #0x2
- bne wait_sdrc_ready
- /* allow DLL powerdown upon hw idle req */
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
- /* Is dll in lock mode? */
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- tst r5, #0x4
- bxne lr @ Return if locked
- /* wait till dll locks */
- adr r7, kick_counter
-wait_dll_lock_timed:
- ldr r4, wait_dll_lock_counter
- add r4, r4, #1
- str r4, [r7, #wait_dll_lock_counter - kick_counter]
- ldr r4, sdrc_dlla_status
- /* Wait 20uS for lock */
- mov r6, #8
-wait_dll_lock:
- subs r6, r6, #0x1
- beq kick_dll
- ldr r5, [r4]
- and r5, r5, #0x4
- cmp r5, #0x4
- bne wait_dll_lock
- bx lr @ Return when locked
-
- /* disable/reenable DLL if not locked */
-kick_dll:
- ldr r4, sdrc_dlla_ctrl
- ldr r5, [r4]
- mov r6, r5
- bic r6, #(1<<3) @ disable dll
- str r6, [r4]
- dsb
- orr r6, r6, #(1<<3) @ enable dll
- str r6, [r4]
- dsb
- ldr r4, kick_counter
- add r4, r4, #1
- str r4, [r7] @ kick_counter
- b wait_dll_lock_timed
-
- .align
-cm_idlest1_core:
- .word CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
- .word CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
- .word SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
- .word SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
- .word PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
- .word PM_PWSTCTRL_MPU_P
-scratchpad_base:
- .word SCRATCHPAD_BASE_P
-sram_base:
- .word SRAM_BASE_P + 0x8000
-sdrc_power:
- .word SDRC_POWER_V
-ttbrbit_mask:
- .word 0xFFFFC000
-table_index_mask:
- .word 0xFFF00000
-table_entry:
- .word 0x00000C02
-cache_pred_disable_mask:
- .word 0xFFFFE7FB
-control_stat:
- .word CONTROL_STAT
-control_mem_rta:
- .word CONTROL_MEM_RTA_CTRL
-kernel_flush:
- .word v7_flush_dcache_all
-l2dis_3630:
- .word 0
- /*
- * When exporting to userspace while the counters are in SRAM,
- * these 2 words need to be at the end to facilitate retrival!
- */
-kick_counter:
- .word 0
-wait_dll_lock_counter:
- .word 0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
- .word . - omap34xx_cpu_suspend
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b..363c91e 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
}
#endif /* CONFIG_PM */
-static int __init omap34xx_sram_init(void)
-{
- _omap3_sram_configure_core_dpll =
- omap_sram_push(omap3_sram_configure_core_dpll,
- omap3_sram_configure_core_dpll_sz);
- omap_push_sram_idle();
- return 0;
-}
-#else
+#endif /* CONFIG_ARCH_OMAP3 */
+
static inline int omap34xx_sram_init(void)
{
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+ omap3_sram_restore_context();
+#endif
return 0;
}
-#endif
int __init omap_sram_init(void)
{
--
1.7.4.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
end of thread, other threads:[~2011-07-13 8:14 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-29 16:40 [PATCH] OMAP3: run the ASM sleep code from DDR jean.pihet
2011-06-29 16:40 ` jean.pihet at newoldbits.com
2011-06-29 17:29 ` Kevin Hilman
2011-06-29 17:29 ` Kevin Hilman
2011-06-29 17:48 ` Jean Pihet
2011-06-29 17:48 ` Jean Pihet
2011-06-29 18:05 ` Russell King - ARM Linux
2011-06-29 18:05 ` Russell King - ARM Linux
2011-06-29 19:06 ` Kevin Hilman
2011-06-29 19:06 ` Kevin Hilman
2011-06-29 21:54 ` Russell King - ARM Linux
2011-06-29 21:54 ` Russell King - ARM Linux
2011-06-29 23:30 ` Kevin Hilman
2011-06-29 23:30 ` Kevin Hilman
2011-06-29 21:45 ` Russell King - ARM Linux
2011-06-29 21:45 ` Russell King - ARM Linux
2011-06-30 8:55 ` Peter De Schrijver
2011-07-12 6:07 ` Pavel Machek
2011-07-12 6:07 ` Pavel Machek
2011-07-13 8:14 ` Paul Walmsley
2011-07-13 8:14 ` Paul Walmsley
-- strict thread matches above, loose matches on Subject: below --
2011-06-17 8:52 jean.pihet
2011-06-17 9:51 ` Santosh Shilimkar
2011-06-24 0:17 ` Kevin Hilman
2011-06-24 8:32 ` Jean Pihet
2011-06-24 14:42 ` Kevin Hilman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.