All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
@ 2011-01-13 16:19 jean.pihet
  2011-01-24 14:29 ` Jean Pihet
  2011-01-29 17:14 ` Santosh Shilimkar
  0 siblings, 2 replies; 17+ messages in thread
From: jean.pihet @ 2011-01-13 16:19 UTC (permalink / raw)
  To: linux-omap; +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),
  . 1368 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).

With this fix the usage for suspend/resume in RETention goes down 312 bytes, so the
gain in SRAM usage for suspend/resume is > 1KB.

Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
in idle with full RET and OFF modes.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.h        |   19 ++-
 arch/arm/mach-omap2/pm34xx.c    |   19 ++-
 arch/arm/mach-omap2/sleep34xx.S |  299 +++++++++++++++++++++++----------------
 3 files changed, 200 insertions(+), 137 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 1c1b0ab..ae9dec0 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -87,18 +87,29 @@ 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);
+
+/* 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 void save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
 
-extern unsigned int omap24xx_idle_loop_suspend_sz;
 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 5b323f2..56ca3cb 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -82,9 +82,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;
@@ -355,9 +354,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);
@@ -439,7 +435,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 */
@@ -996,10 +992,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);
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 98d8232..ced85b5 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -163,8 +163,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.
@@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
 	 *   3 - Both L1 and L2 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:
@@ -282,7 +290,31 @@ clean_l2:
 	mov	lr, pc
 	bx	r1
 
-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).
+ */
+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
@@ -315,15 +347,111 @@ omap3_do_wfi:
 	nop
 	nop
 	nop
-	bl wait_sdrc_ok
+
+/*
+ * wait_sdrc_ok 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 SDRAM.
+ */
+
+/* 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]
+
+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 */
+wait_dll_lock_timed:
+	ldr	r4, wait_dll_lock_counter
+	add	r4, r4, #1
+	str	r4, wait_dll_lock_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, kick_counter
+	b	wait_dll_lock_timed
 
 /*
  * ===================================
  * == Exit point from non-OFF modes ==
  * ===================================
  */
+exit_nonoff_modes:
 	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
+
 
 /*
  * ==============================
@@ -339,6 +467,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
@@ -357,7 +489,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
@@ -600,12 +733,41 @@ usettbr0:
  */
 	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
 ENTRY(es3_sdrc_fix)
 	ldr	r4, sdrc_syscfg		@ get config addr
@@ -634,6 +796,9 @@ ENTRY(es3_sdrc_fix)
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr
 
+/*
+ * Local variables
+ */
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
 sdrc_mr_0:
@@ -650,119 +815,3 @@ sdrc_manual_1:
 	.word	SDRC_MANUAL_1_P
 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]
-
-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 */
-wait_dll_lock_timed:
-	ldr	r4, wait_dll_lock_counter
-	add	r4, r4, #1
-	str	r4, wait_dll_lock_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, kick_counter
-	b	wait_dll_lock_timed
-
-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
-
-ENTRY(omap34xx_cpu_suspend_sz)
-	.word	. - omap34xx_cpu_suspend
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-13 16:19 [RFC/PATCH] OMAP3: run the ASM sleep code from DDR jean.pihet
@ 2011-01-24 14:29 ` Jean Pihet
  2011-01-27 10:13   ` Vishwanath Sripathy
  2011-01-29 17:14 ` Santosh Shilimkar
  1 sibling, 1 reply; 17+ messages in thread
From: Jean Pihet @ 2011-01-24 14:29 UTC (permalink / raw)
  To: linux-omap; +Cc: Jean Pihet

On Thu, Jan 13, 2011 at 5:19 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),
>  . 1368 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).
>
> With this fix the usage for suspend/resume in RETention goes down 312 bytes, so the
> gain in SRAM usage for suspend/resume is > 1KB.
>
> Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
> in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>

Is there any feedback on this code?
This change would need some more testing on all OMAP3 platforms,
especially on the 36xx platforms that I do not have at hand.

Comments are welcome!

Regards,
Jean

> ---
>  arch/arm/mach-omap2/pm.h        |   19 ++-
>  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
>  arch/arm/mach-omap2/sleep34xx.S |  299 +++++++++++++++++++++++----------------
>  3 files changed, 200 insertions(+), 137 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 1c1b0ab..ae9dec0 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -87,18 +87,29 @@ 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);
> +
> +/* 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 void save_secure_ram_context(u32 *addr);
> -extern void omap3_save_scratchpad_contents(void);
>
> -extern unsigned int omap24xx_idle_loop_suspend_sz;
>  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 5b323f2..56ca3cb 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -82,9 +82,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;
> @@ -355,9 +354,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);
> @@ -439,7 +435,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 */
> @@ -996,10 +992,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);
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
> index 98d8232..ced85b5 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -163,8 +163,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.
> @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
>         *   3 - Both L1 and L2 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:
> @@ -282,7 +290,31 @@ clean_l2:
>        mov     lr, pc
>        bx      r1
>
> -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).
> + */
> +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
> @@ -315,15 +347,111 @@ omap3_do_wfi:
>        nop
>        nop
>        nop
> -       bl wait_sdrc_ok
> +
> +/*
> + * wait_sdrc_ok 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 SDRAM.
> + */
> +
> +/* 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]
> +
> +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 */
> +wait_dll_lock_timed:
> +       ldr     r4, wait_dll_lock_counter
> +       add     r4, r4, #1
> +       str     r4, wait_dll_lock_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, kick_counter
> +       b       wait_dll_lock_timed
>
>  /*
>  * ===================================
>  * == Exit point from non-OFF modes ==
>  * ===================================
>  */
> +exit_nonoff_modes:
>        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
> +
>
>  /*
>  * ==============================
> @@ -339,6 +467,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
> @@ -357,7 +489,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
> @@ -600,12 +733,41 @@ usettbr0:
>  */
>        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
>  ENTRY(es3_sdrc_fix)
>        ldr     r4, sdrc_syscfg         @ get config addr
> @@ -634,6 +796,9 @@ ENTRY(es3_sdrc_fix)
>        str     r5, [r4]                @ kick off refreshes
>        bx      lr
>
> +/*
> + * Local variables
> + */
>  sdrc_syscfg:
>        .word   SDRC_SYSCONFIG_P
>  sdrc_mr_0:
> @@ -650,119 +815,3 @@ sdrc_manual_1:
>        .word   SDRC_MANUAL_1_P
>  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]
> -
> -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 */
> -wait_dll_lock_timed:
> -       ldr     r4, wait_dll_lock_counter
> -       add     r4, r4, #1
> -       str     r4, wait_dll_lock_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, kick_counter
> -       b       wait_dll_lock_timed
> -
> -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
> -
> -ENTRY(omap34xx_cpu_suspend_sz)
> -       .word   . - omap34xx_cpu_suspend
> --
> 1.7.2.3
>
>
--
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] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-24 14:29 ` Jean Pihet
@ 2011-01-27 10:13   ` Vishwanath Sripathy
  2011-01-27 13:50     ` Jean Pihet
  0 siblings, 1 reply; 17+ messages in thread
From: Vishwanath Sripathy @ 2011-01-27 10:13 UTC (permalink / raw)
  To: Jean Pihet, linux-omap; +Cc: Jean Pihet-XID

Jean,

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Jean Pihet
> Sent: Monday, January 24, 2011 7:59 PM
> To: linux-omap@vger.kernel.org
> Cc: Jean Pihet
> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>
> On Thu, Jan 13, 2011 at 5:19 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),
> >  . 1368 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).
> >
> > With this fix the usage for suspend/resume in RETention goes down
> 312 bytes, so the
> > gain in SRAM usage for suspend/resume is > 1KB.
> >
> > Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
> > in idle with full RET and OFF modes.
> >
> > Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> Is there any feedback on this code?
> This change would need some more testing on all OMAP3 platforms,
> especially on the 36xx platforms that I do not have at hand.
I tested this patch on ZOOM3 (OMAP3630) using kevin's PM branch for both
retention and off in CPUIdle and suspend path and it seems to work fine.
You can add
Tested-by: Vishwanath BS <Vishwanath.bs@ti.com>

Vishwa
>
> Comments are welcome!
>
> Regards,
> Jean
>
> > ---
> >  arch/arm/mach-omap2/pm.h        |   19 ++-
> >  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
> >  arch/arm/mach-omap2/sleep34xx.S |  299
> +++++++++++++++++++++++----------------
> >  3 files changed, 200 insertions(+), 137 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-
> omap2/pm.h
> > index 1c1b0ab..ae9dec0 100644
> > --- a/arch/arm/mach-omap2/pm.h
> > +++ b/arch/arm/mach-omap2/pm.h
> > @@ -87,18 +87,29 @@ 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);
> > +
> > +/* 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 void save_secure_ram_context(u32 *addr);
> > -extern void omap3_save_scratchpad_contents(void);
> >
> > -extern unsigned int omap24xx_idle_loop_suspend_sz;
> >  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 5b323f2..56ca3cb 100644
> > --- a/arch/arm/mach-omap2/pm34xx.c
> > +++ b/arch/arm/mach-omap2/pm34xx.c
> > @@ -82,9 +82,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;
> > @@ -355,9 +354,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);
> > @@ -439,7 +435,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 */
> > @@ -996,10 +992,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);
> > diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
> omap2/sleep34xx.S
> > index 98d8232..ced85b5 100644
> > --- a/arch/arm/mach-omap2/sleep34xx.S
> > +++ b/arch/arm/mach-omap2/sleep34xx.S
> > @@ -163,8 +163,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.
> > @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
> >         *   3 - Both L1 and L2 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:
> > @@ -282,7 +290,31 @@ clean_l2:
> >        mov     lr, pc
> >        bx      r1
> >
> > -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).
> > + */
> > +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
> > @@ -315,15 +347,111 @@ omap3_do_wfi:
> >        nop
> >        nop
> >        nop
> > -       bl wait_sdrc_ok
> > +
> > +/*
> > + * wait_sdrc_ok 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 SDRAM.
> > + */
> > +
> > +/* 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]
> > +
> > +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 */
> > +wait_dll_lock_timed:
> > +       ldr     r4, wait_dll_lock_counter
> > +       add     r4, r4, #1
> > +       str     r4, wait_dll_lock_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, kick_counter
> > +       b       wait_dll_lock_timed
> >
> >  /*
> >  * ===================================
> >  * == Exit point from non-OFF modes ==
> >  * ===================================
> >  */
> > +exit_nonoff_modes:
> >        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
> > +
> >
> >  /*
> >  * ==============================
> > @@ -339,6 +467,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
> > @@ -357,7 +489,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
> > @@ -600,12 +733,41 @@ usettbr0:
> >  */
> >        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
> >  ENTRY(es3_sdrc_fix)
> >        ldr     r4, sdrc_syscfg         @ get config addr
> > @@ -634,6 +796,9 @@ ENTRY(es3_sdrc_fix)
> >        str     r5, [r4]                @ kick off refreshes
> >        bx      lr
> >
> > +/*
> > + * Local variables
> > + */
> >  sdrc_syscfg:
> >        .word   SDRC_SYSCONFIG_P
> >  sdrc_mr_0:
> > @@ -650,119 +815,3 @@ sdrc_manual_1:
> >        .word   SDRC_MANUAL_1_P
> >  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]
> > -
> > -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 */
> > -wait_dll_lock_timed:
> > -       ldr     r4, wait_dll_lock_counter
> > -       add     r4, r4, #1
> > -       str     r4, wait_dll_lock_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, kick_counter
> > -       b       wait_dll_lock_timed
> > -
> > -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
> > -
> > -ENTRY(omap34xx_cpu_suspend_sz)
> > -       .word   . - omap34xx_cpu_suspend
> > --
> > 1.7.2.3
> >
> >
> --
> 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
--
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] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-27 10:13   ` Vishwanath Sripathy
@ 2011-01-27 13:50     ` Jean Pihet
  0 siblings, 0 replies; 17+ messages in thread
From: Jean Pihet @ 2011-01-27 13:50 UTC (permalink / raw)
  To: Vishwanath Sripathy; +Cc: linux-omap, Jean Pihet-XID

On Thu, Jan 27, 2011 at 11:13 AM, Vishwanath Sripathy
<vishwanath.bs@ti.com> wrote:
> Jean,
>
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
>> owner@vger.kernel.org] On Behalf Of Jean Pihet
>> Sent: Monday, January 24, 2011 7:59 PM
>> To: linux-omap@vger.kernel.org
>> Cc: Jean Pihet
>> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>
>> On Thu, Jan 13, 2011 at 5:19 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),
>> >  . 1368 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).
>> >
>> > With this fix the usage for suspend/resume in RETention goes down
>> 312 bytes, so the
>> > gain in SRAM usage for suspend/resume is > 1KB.
>> >
>> > Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
>> > in idle with full RET and OFF modes.
>> >
>> > Signed-off-by: Jean Pihet <j-pihet@ti.com>
>>
>> Is there any feedback on this code?
>> This change would need some more testing on all OMAP3 platforms,
>> especially on the 36xx platforms that I do not have at hand.
> I tested this patch on ZOOM3 (OMAP3630) using kevin's PM branch for both
> retention and off in CPUIdle and suspend path and it seems to work fine.
> You can add
> Tested-by: Vishwanath BS <Vishwanath.bs@ti.com>
Thanks Vishwa!

Regards,
Jean

>
> Vishwa
>>
>> Comments are welcome!
>>
>> Regards,
>> Jean
>>
>> > ---
>> >  arch/arm/mach-omap2/pm.h        |   19 ++-
>> >  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
>> >  arch/arm/mach-omap2/sleep34xx.S |  299
>> +++++++++++++++++++++++----------------
>> >  3 files changed, 200 insertions(+), 137 deletions(-)
>> >
>> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-
>> omap2/pm.h
>> > index 1c1b0ab..ae9dec0 100644
>> > --- a/arch/arm/mach-omap2/pm.h
>> > +++ b/arch/arm/mach-omap2/pm.h
>> > @@ -87,18 +87,29 @@ 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);
>> > +
>> > +/* 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 void save_secure_ram_context(u32 *addr);
>> > -extern void omap3_save_scratchpad_contents(void);
>> >
>> > -extern unsigned int omap24xx_idle_loop_suspend_sz;
>> >  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 5b323f2..56ca3cb 100644
>> > --- a/arch/arm/mach-omap2/pm34xx.c
>> > +++ b/arch/arm/mach-omap2/pm34xx.c
>> > @@ -82,9 +82,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;
>> > @@ -355,9 +354,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);
>> > @@ -439,7 +435,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 */
>> > @@ -996,10 +992,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);
>> > diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
>> omap2/sleep34xx.S
>> > index 98d8232..ced85b5 100644
>> > --- a/arch/arm/mach-omap2/sleep34xx.S
>> > +++ b/arch/arm/mach-omap2/sleep34xx.S
>> > @@ -163,8 +163,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.
>> > @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
>> >         *   3 - Both L1 and L2 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:
>> > @@ -282,7 +290,31 @@ clean_l2:
>> >        mov     lr, pc
>> >        bx      r1
>> >
>> > -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).
>> > + */
>> > +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
>> > @@ -315,15 +347,111 @@ omap3_do_wfi:
>> >        nop
>> >        nop
>> >        nop
>> > -       bl wait_sdrc_ok
>> > +
>> > +/*
>> > + * wait_sdrc_ok 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 SDRAM.
>> > + */
>> > +
>> > +/* 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]
>> > +
>> > +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 */
>> > +wait_dll_lock_timed:
>> > +       ldr     r4, wait_dll_lock_counter
>> > +       add     r4, r4, #1
>> > +       str     r4, wait_dll_lock_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, kick_counter
>> > +       b       wait_dll_lock_timed
>> >
>> >  /*
>> >  * ===================================
>> >  * == Exit point from non-OFF modes ==
>> >  * ===================================
>> >  */
>> > +exit_nonoff_modes:
>> >        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
>> > +
>> >
>> >  /*
>> >  * ==============================
>> > @@ -339,6 +467,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
>> > @@ -357,7 +489,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
>> > @@ -600,12 +733,41 @@ usettbr0:
>> >  */
>> >        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
>> >  ENTRY(es3_sdrc_fix)
>> >        ldr     r4, sdrc_syscfg         @ get config addr
>> > @@ -634,6 +796,9 @@ ENTRY(es3_sdrc_fix)
>> >        str     r5, [r4]                @ kick off refreshes
>> >        bx      lr
>> >
>> > +/*
>> > + * Local variables
>> > + */
>> >  sdrc_syscfg:
>> >        .word   SDRC_SYSCONFIG_P
>> >  sdrc_mr_0:
>> > @@ -650,119 +815,3 @@ sdrc_manual_1:
>> >        .word   SDRC_MANUAL_1_P
>> >  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]
>> > -
>> > -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 */
>> > -wait_dll_lock_timed:
>> > -       ldr     r4, wait_dll_lock_counter
>> > -       add     r4, r4, #1
>> > -       str     r4, wait_dll_lock_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, kick_counter
>> > -       b       wait_dll_lock_timed
>> > -
>> > -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
>> > -
>> > -ENTRY(omap34xx_cpu_suspend_sz)
>> > -       .word   . - omap34xx_cpu_suspend
>> > --
>> > 1.7.2.3
>> >
>> >
>> --
>> 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
>
--
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] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-13 16:19 [RFC/PATCH] OMAP3: run the ASM sleep code from DDR jean.pihet
  2011-01-24 14:29 ` Jean Pihet
@ 2011-01-29 17:14 ` Santosh Shilimkar
  2011-01-30  5:57   ` Santosh Shilimkar
  1 sibling, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-01-29 17:14 UTC (permalink / raw)
  To: jean.pihet, linux-omap; +Cc: Jean Pihet-XID

Jean,
> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of jean.pihet@newoldbits.com
> Sent: Thursday, January 13, 2011 9:49 PM
> To: linux-omap@vger.kernel.org
> Cc: Jean Pihet
> Subject: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>
> 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),
>   . 1368 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).
>
> With this fix the usage for suspend/resume in RETention goes down
> 312 bytes, so the
> gain in SRAM usage for suspend/resume is > 1KB.
>
> Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
> in idle with full RET and OFF modes.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> ---
>  arch/arm/mach-omap2/pm.h        |   19 ++-
>  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
>  arch/arm/mach-omap2/sleep34xx.S |  299 +++++++++++++++++++++++-----
> -----------
>  3 files changed, 200 insertions(+), 137 deletions(-)
>
[...]

> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
> omap2/sleep34xx.S
> index 98d8232..ced85b5 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -163,8 +163,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.
> @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
>  	 *   3 - Both L1 and L2 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)

Why is this distinction? For non-low power modes
it should be even safer to issue WFI from DDR itself.

Do I miss any errata here ?

> +	 */
> +	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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-29 17:14 ` Santosh Shilimkar
@ 2011-01-30  5:57   ` Santosh Shilimkar
  2011-01-31 10:36     ` Jean Pihet
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-01-30  5:57 UTC (permalink / raw)
  To: jean.pihet, linux-omap; +Cc: Jean Pihet-XID

> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
> Sent: Saturday, January 29, 2011 10:45 PM
> To: jean.pihet@newoldbits.com; linux-omap@vger.kernel.org
> Cc: Jean Pihet-XID
> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>
> Jean,
> > -----Original Message-----
> > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> > owner@vger.kernel.org] On Behalf Of jean.pihet@newoldbits.com
> > Sent: Thursday, January 13, 2011 9:49 PM
> > To: linux-omap@vger.kernel.org
> > Cc: Jean Pihet
> > Subject: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
> >
> > 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),
> >   . 1368 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).
> >
> > With this fix the usage for suspend/resume in RETention goes down
> > 312 bytes, so the
> > gain in SRAM usage for suspend/resume is > 1KB.
> >
> > Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
> > in idle with full RET and OFF modes.
> >
> > Signed-off-by: Jean Pihet <j-pihet@ti.com>
> > ---
> >  arch/arm/mach-omap2/pm.h        |   19 ++-
> >  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
> >  arch/arm/mach-omap2/sleep34xx.S |  299 +++++++++++++++++++++++---
> --
> > -----------
> >  3 files changed, 200 insertions(+), 137 deletions(-)
> >
> [...]
>
> > diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
> > omap2/sleep34xx.S
> > index 98d8232..ced85b5 100644
> > --- a/arch/arm/mach-omap2/sleep34xx.S
> > +++ b/arch/arm/mach-omap2/sleep34xx.S
> > @@ -163,8 +163,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.
> > @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
> >  	 *   3 - Both L1 and L2 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)
>
> Why is this distinction? For non-low power modes
> it should be even safer to issue WFI from DDR itself.
>
> Do I miss any errata here ?
>
Looking further into code, I also noticed that the
DDR self refresh is attempted for every WFI. This
certainly isn't correct and should be attempted only
if core OFF or RET is attempted. Putting DDR to
self refresh comes with latency cost and you
certainly don't want to incur that for lower C states
where may be just MPU hits lower states.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-30  5:57   ` Santosh Shilimkar
@ 2011-01-31 10:36     ` Jean Pihet
  2011-01-31 11:00       ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Jean Pihet @ 2011-01-31 10:36 UTC (permalink / raw)
  To: Santosh Shilimkar; +Cc: linux-omap, Jean Pihet-XID

Hi Santosh,

On Sun, Jan 30, 2011 at 6:57 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
>> Sent: Saturday, January 29, 2011 10:45 PM
>> To: jean.pihet@newoldbits.com; linux-omap@vger.kernel.org
>> Cc: Jean Pihet-XID
>> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>
>> Jean,
>> > -----Original Message-----
>> > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
>> > owner@vger.kernel.org] On Behalf Of jean.pihet@newoldbits.com
>> > Sent: Thursday, January 13, 2011 9:49 PM
>> > To: linux-omap@vger.kernel.org
>> > Cc: Jean Pihet
>> > Subject: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>> >
>> > 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),
>> >   . 1368 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).
>> >
>> > With this fix the usage for suspend/resume in RETention goes down
>> > 312 bytes, so the
>> > gain in SRAM usage for suspend/resume is > 1KB.
>> >
>> > Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
>> > in idle with full RET and OFF modes.
>> >
>> > Signed-off-by: Jean Pihet <j-pihet@ti.com>
>> > ---
>> >  arch/arm/mach-omap2/pm.h        |   19 ++-
>> >  arch/arm/mach-omap2/pm34xx.c    |   19 ++-
>> >  arch/arm/mach-omap2/sleep34xx.S |  299 +++++++++++++++++++++++---
>> --
>> > -----------
>> >  3 files changed, 200 insertions(+), 137 deletions(-)
>> >
>> [...]
>>
>> > diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
>> > omap2/sleep34xx.S
>> > index 98d8232..ced85b5 100644
>> > --- a/arch/arm/mach-omap2/sleep34xx.S
>> > +++ b/arch/arm/mach-omap2/sleep34xx.S
>> > @@ -163,8 +163,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.
>> > @@ -181,9 +183,15 @@ ENTRY(omap34xx_cpu_suspend)
>> >      *   3 - Both L1 and L2 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)
>>
>> Why is this distinction? For non-low power modes
>> it should be even safer to issue WFI from DDR itself.
>>
>> Do I miss any errata here ?
For non-OFF modes the erratum ID i581 WA forces us to restore the SDRC
state before accessing the SDRAM, cf. wait_sdrc_ok that implements
that. Given that the non-OFF mode triggering WFI needs to be run from
SRAM.

> Looking further into code, I also noticed that the
> DDR self refresh is attempted for every WFI. This
> certainly isn't correct and should be attempted only
> if core OFF or RET is attempted. Putting DDR to
> self refresh comes with latency cost and you
> certainly don't want to incur that for lower C states
> where may be just MPU hits lower states.
The DDR self refresh is enabled at each WFI but not necessarily hit.
It is actually triggered by the CORE idle request which depends on the
settings, the dependencies, the HW states... For example the CORE
state depends on the MPU state so if the MPU stays ON running
instructions the CORE will stay ON as well.

Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
already locked, e.g. if the CORE did not hit a low power state. Since
the actual CORE hit state is unknow after wake-up from WFI the
wait_sdrc_ok code always run at wake-up from MPU RET.

Does that makes sense?

>
> Regards,
> Santosh
>

Thanks,
Jean
--
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] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-31 10:36     ` Jean Pihet
@ 2011-01-31 11:00       ` Santosh Shilimkar
  2011-02-01 11:23         ` Jean Pihet
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-01-31 11:00 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, Jean Pihet-XID

> -----Original Message-----
> From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
> Sent: Monday, January 31, 2011 4:07 PM
> To: Santosh Shilimkar
> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>
> Hi Santosh,
[.....]

> >> > +    * 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)
> >>
> >> Why is this distinction? For non-low power modes
> >> it should be even safer to issue WFI from DDR itself.
> >>
> >> Do I miss any errata here ?
> For non-OFF modes the erratum ID i581 WA forces us to restore the
> SDRC
> state before accessing the SDRAM, cf. wait_sdrc_ok that implements
> that. Given that the non-OFF mode triggering WFI needs to be run
> from
> SRAM.
>
The errata is applicable when CORE hits low power states and DPLL
can autoidle. Not sure how are linking this with all non-OFF modes.

> > Looking further into code, I also noticed that the
> > DDR self refresh is attempted for every WFI. This
> > certainly isn't correct and should be attempted only
> > if core OFF or RET is attempted. Putting DDR to
> > self refresh comes with latency cost and you
> > certainly don't want to incur that for lower C states
> > where may be just MPU hits lower states.
> The DDR self refresh is enabled at each WFI but not necessarily hit.
> It is actually triggered by the CORE idle request which depends on
> the
> settings, the dependencies, the HW states... For example the CORE
> state depends on the MPU state so if the MPU stays ON running
> instructions the CORE will stay ON as well.
>
> Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
> already locked, e.g. if the CORE did not hit a low power state.
> Since
> the actual CORE hit state is unknow after wake-up from WFI the
> wait_sdrc_ok code always run at wake-up from MPU RET.
>
> Does that makes sense?
>
Actually not. Rather I will separate only the scenario's
where CORE low power targets are attempted and only have
that code run from SRAM.

There are scenario's where CORE can be active because MODEM,
DSP and MPU can still hit RET, OFF. And here, the errata
isn't applicable.

Unless I missed something here, I think in the code we check
the the CORE attempted state and based on that we can do a
normal WFI from DDR (no self rfersh) or WFI from
SRAM with self refresh enabled.

Regards,
Santosh
--
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] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-01-31 11:00       ` Santosh Shilimkar
@ 2011-02-01 11:23         ` Jean Pihet
  2011-02-01 11:31           ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Jean Pihet @ 2011-02-01 11:23 UTC (permalink / raw)
  To: Santosh Shilimkar; +Cc: linux-omap, Jean Pihet-XID

Hi Santosh,

On Mon, Jan 31, 2011 at 12:00 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
>> Sent: Monday, January 31, 2011 4:07 PM
>> To: Santosh Shilimkar
>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>
>> Hi Santosh,
> [.....]
>
>> >> > +    * 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)
>> >>
>> >> Why is this distinction? For non-low power modes
>> >> it should be even safer to issue WFI from DDR itself.
>> >>
>> >> Do I miss any errata here ?
>> For non-OFF modes the erratum ID i581 WA forces us to restore the
>> SDRC
>> state before accessing the SDRAM, cf. wait_sdrc_ok that implements
>> that. Given that the non-OFF mode triggering WFI needs to be run
>> from
>> SRAM.
>>
> The errata is applicable when CORE hits low power states and DPLL
> can autoidle. Not sure how are linking this with all non-OFF modes.
>
>> > Looking further into code, I also noticed that the
>> > DDR self refresh is attempted for every WFI. This
>> > certainly isn't correct and should be attempted only
>> > if core OFF or RET is attempted. Putting DDR to
>> > self refresh comes with latency cost and you
>> > certainly don't want to incur that for lower C states
>> > where may be just MPU hits lower states.
>> The DDR self refresh is enabled at each WFI but not necessarily hit.
>> It is actually triggered by the CORE idle request which depends on
>> the
>> settings, the dependencies, the HW states... For example the CORE
>> state depends on the MPU state so if the MPU stays ON running
>> instructions the CORE will stay ON as well.
>>
>> Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
>> already locked, e.g. if the CORE did not hit a low power state.
>> Since
>> the actual CORE hit state is unknow after wake-up from WFI the
>> wait_sdrc_ok code always run at wake-up from MPU RET.
>>
>> Does that makes sense?
>>
> Actually not. Rather I will separate only the scenario's
> where CORE low power targets are attempted and only have
> that code run from SRAM.
>
> There are scenario's where CORE can be active because MODEM,
> DSP and MPU can still hit RET, OFF. And here, the errata
> isn't applicable.
>
> Unless I missed something here, I think in the code we check
> the the CORE attempted state and based on that we can do a
> normal WFI from DDR (no self rfersh) or WFI from
> SRAM with self refresh enabled.
No. Only the MPU attempted state is checked (this actually is the
'save_state' parameter passed to omap_cpu_suspend).
So it makes sense to check the CORE attempted state in order to decide
to run the WFI from internal SRAM or DDR.

The MPU attempted state is used to decide whether to save the MPU/L1/L2 context.

>
> Regards,
> Santosh
>

Thanks,
Jean
--
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] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-02-01 11:23         ` Jean Pihet
@ 2011-02-01 11:31           ` Santosh Shilimkar
  2011-02-04 11:39             ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-02-01 11:31 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, Jean Pihet-XID

> -----Original Message-----
> From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
> Sent: Tuesday, February 01, 2011 4:53 PM
> To: Santosh Shilimkar
> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>

[...]
> >> Does that makes sense?
> >>
> > Actually not. Rather I will separate only the scenario's
> > where CORE low power targets are attempted and only have
> > that code run from SRAM.
> >
> > There are scenario's where CORE can be active because MODEM,
> > DSP and MPU can still hit RET, OFF. And here, the errata
> > isn't applicable.
> >
> > Unless I missed something here, I think in the code we check
> > the the CORE attempted state and based on that we can do a
> > normal WFI from DDR (no self rfersh) or WFI from
> > SRAM with self refresh enabled.
> No. Only the MPU attempted state is checked (this actually is the
> 'save_state' parameter passed to omap_cpu_suspend).
> So it makes sense to check the CORE attempted state in order to
> decide
> to run the WFI from internal SRAM or DDR.
>
> The MPU attempted state is used to decide whether to save the
> MPU/L1/L2 context.
>
Looks like you miss-understood my point. As I understand from
errata, as long as core clock domain can idle with core
dpll divider auto idle enabled, the errata is applicable.

So the only check needed is to see if the core clockdomain
hw_auto or sw sleep is enabled.

If it is suppose to be not idle(we force few C-states
where CORE inactive is avoided for faster response),
we can execute WFI from DDR with not enabling
self refresh.

Rest of the scenario can follow the SRAM path.

Hope this is clear to you.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-02-01 11:31           ` Santosh Shilimkar
@ 2011-02-04 11:39             ` Santosh Shilimkar
  2011-06-16 15:30               ` Pihet-XID, Jean
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-02-04 11:39 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, Jean Pihet-XID

[-- Attachment #1: Type: text/plain, Size: 16890 bytes --]

Jean,
> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
> Sent: Tuesday, February 01, 2011 5:01 PM
> To: Jean Pihet
> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>
> > -----Original Message-----
> > From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
> > Sent: Tuesday, February 01, 2011 4:53 PM
> > To: Santosh Shilimkar
> > Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
> > Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
> >
>
> [...]
> > >> Does that makes sense?
> > >>
> > > Actually not. Rather I will separate only the scenario's
> > > where CORE low power targets are attempted and only have
> > > that code run from SRAM.
> > >
> > > There are scenario's where CORE can be active because MODEM,
> > > DSP and MPU can still hit RET, OFF. And here, the errata
> > > isn't applicable.
> > >
> > > Unless I missed something here, I think in the code we check
> > > the the CORE attempted state and based on that we can do a
> > > normal WFI from DDR (no self rfersh) or WFI from
> > > SRAM with self refresh enabled.
> > No. Only the MPU attempted state is checked (this actually is the
> > 'save_state' parameter passed to omap_cpu_suspend).
> > So it makes sense to check the CORE attempted state in order to
> > decide
> > to run the WFI from internal SRAM or DDR.
> >
> > The MPU attempted state is used to decide whether to save the
> > MPU/L1/L2 context.
> >
> Looks like you miss-understood my point. As I understand from
> errata, as long as core clock domain can idle with core
> dpll divider auto idle enabled, the errata is applicable.
>
> So the only check needed is to see if the core clockdomain
> hw_auto or sw sleep is enabled.
>
> If it is suppose to be not idle(we force few C-states
> where CORE inactive is avoided for faster response),
> we can execute WFI from DDR with not enabling
> self refresh.
>
> Rest of the scenario can follow the SRAM path.
>
> Hope this is clear to you.

As per further discussion, I have updated your
patch to address above by using core clockdomain
state.

Have tested OFF and RET with this new update and they
work as expected. Feel free to update further if needed.

------
>From 49fe8164a40431807495638ec23639cc9bc53cb9 Mon Sep 17 00:00:00 2001
From: Jean Pihet <j-pihet@ti.com>
Date: Sat, 29 Jan 2011 20:51:19 +0530
Subject: [PATCH] OMAP3: run the ASM sleep code from DDR

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),
  . 1368 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).

With this fix the usage for suspend/resume in RETention goes down 312
bytes, so the
gain in SRAM usage for suspend/resume is > 1KB.

Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
in idle with full RET and OFF modes.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.h        |   19 ++-
 arch/arm/mach-omap2/pm34xx.c    |   19 ++-
 arch/arm/mach-omap2/sleep34xx.S |  321
+++++++++++++++++++++++----------------
 3 files changed, 219 insertions(+), 140 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 1c1b0ab..ae9dec0 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -87,18 +87,29 @@ 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);
+
+/* 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 void save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);

-extern unsigned int omap24xx_idle_loop_suspend_sz;
 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 1b81e8d..cdfd627 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;
@@ -357,9 +356,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);
@@ -444,7 +440,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();

 	if (is_suspending())
@@ -993,10 +989,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);
diff --git a/arch/arm/mach-omap2/sleep34xx.S
b/arch/arm/mach-omap2/sleep34xx.S
index 98d8232..8a987f7 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -42,6 +42,7 @@
 					OMAP3430_PM_PREPWSTST
 #define PM_PWSTCTRL_MPU_P	OMAP3430_PRM_BASE + MPU_MOD +
OMAP2_PM_PWSTCTRL
 #define CM_IDLEST1_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
+#define CM_CLKSTCTRL_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD,
OMAP2_CM_CLKSTCTRL)
 #define CM_IDLEST_CKGEN_V	OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST)
 #define SRAM_BASE_P		OMAP3_SRAM_PA
 #define CONTROL_STAT		OMAP343X_CTRL_BASE +
OMAP343X_CONTROL_STATUS
@@ -163,8 +164,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.
@@ -181,9 +184,15 @@ ENTRY(omap34xx_cpu_suspend)
 	 *   3 - Both L1 and L2 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:
@@ -268,7 +277,7 @@ clean_caches:
 	 * mcr	p15, 0, r11, c7, c11, 1
 	 */
 	cmp	r1, #0x1 		@ Check whether L2 inval is
required
-	beq	omap3_do_wfi
+	beq	do_WFI

 clean_l2:
 	/*
@@ -282,7 +291,44 @@ clean_l2:
 	mov	lr, pc
 	bx	r1

-omap3_do_wfi:
+do_WFI:
+	ldr	r4, cm_clkstctrl_core	@ read the CLKSTCTRL_CORE
+	ldr	r5, [r4]		@ read the contents of
CLKSTCTRL_CORE
+	and	r5, r5, #0x3
+	cmp	r5, #0x3
+	beq	omap3_do_wfi		@ Jumpt to SRAM function
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+
+	wfi				@ wait for interrupt
+
+	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+
+
+/*
+ * 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).
+ */
+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
@@ -302,7 +348,7 @@ omap3_do_wfi:

 /*
  * ===================================
- * == Resume path for non-OFF modes ==
+ * == Resume path for OFF/RET modes ==
  * ===================================
  */
 	nop
@@ -315,15 +361,113 @@ omap3_do_wfi:
 	nop
 	nop
 	nop
-	bl wait_sdrc_ok
+
+/*
+ * wait_sdrc_ok 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 SDRAM.
+ */
+
+/* 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]
+
+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 */
+wait_dll_lock_timed:
+	ldr	r4, wait_dll_lock_counter
+	add	r4, r4, #1
+	str	r4, wait_dll_lock_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, kick_counter
+	b	wait_dll_lock_timed

 /*
  * ===================================
- * == Exit point from non-OFF modes ==
+ * == Exit point from OFF/RET modes ==
  * ===================================
  */
+exit_nonoff_modes:
 	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_clkstctrl_core:
+	.word CM_CLKSTCTRL_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
+

 /*
  * ==============================
@@ -339,6 +483,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
@@ -357,7 +505,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
@@ -600,12 +749,41 @@ usettbr0:
  */
 	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
 ENTRY(es3_sdrc_fix)
 	ldr	r4, sdrc_syscfg		@ get config addr
@@ -634,6 +812,9 @@ ENTRY(es3_sdrc_fix)
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr

+/*
+ * Local variables
+ */
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
 sdrc_mr_0:
@@ -650,119 +831,3 @@ sdrc_manual_1:
 	.word	SDRC_MANUAL_1_P
 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]
-
-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 */
-wait_dll_lock_timed:
-	ldr	r4, wait_dll_lock_counter
-	add	r4, r4, #1
-	str	r4, wait_dll_lock_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, kick_counter
-	b	wait_dll_lock_timed
-
-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
-
-ENTRY(omap34xx_cpu_suspend_sz)
-	.word	. - omap34xx_cpu_suspend
-- 
1.6.0.4

[-- Attachment #2: 0001-OMAP3-run-the-ASM-sleep-code-from-DDR.patch --]
[-- Type: application/octet-stream, Size: 14655 bytes --]

From 49fe8164a40431807495638ec23639cc9bc53cb9 Mon Sep 17 00:00:00 2001
From: Jean Pihet <j-pihet@ti.com>
Date: Sat, 29 Jan 2011 20:51:19 +0530
Subject: [PATCH] OMAP3: run the ASM sleep code from DDR

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),
  . 1368 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).

With this fix the usage for suspend/resume in RETention goes down 312 bytes, so the
gain in SRAM usage for suspend/resume is > 1KB.

Tested on OMAP3EVM, Beagleboard (ES2.x) and N900 (ES3.1)
in idle with full RET and OFF modes.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.h        |   19 ++-
 arch/arm/mach-omap2/pm34xx.c    |   19 ++-
 arch/arm/mach-omap2/sleep34xx.S |  321 +++++++++++++++++++++++----------------
 3 files changed, 219 insertions(+), 140 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 1c1b0ab..ae9dec0 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -87,18 +87,29 @@ 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);
+
+/* 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 void save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
 
-extern unsigned int omap24xx_idle_loop_suspend_sz;
 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 1b81e8d..cdfd627 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;
@@ -357,9 +356,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);
@@ -444,7 +440,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();
 
 	if (is_suspending())
@@ -993,10 +989,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);
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 98d8232..8a987f7 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -42,6 +42,7 @@
 					OMAP3430_PM_PREPWSTST
 #define PM_PWSTCTRL_MPU_P	OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL
 #define CM_IDLEST1_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
+#define CM_CLKSTCTRL_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL)
 #define CM_IDLEST_CKGEN_V	OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST)
 #define SRAM_BASE_P		OMAP3_SRAM_PA
 #define CONTROL_STAT		OMAP343X_CTRL_BASE + OMAP343X_CONTROL_STATUS
@@ -163,8 +164,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.
@@ -181,9 +184,15 @@ ENTRY(omap34xx_cpu_suspend)
 	 *   3 - Both L1 and L2 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:
@@ -268,7 +277,7 @@ clean_caches:
 	 * mcr	p15, 0, r11, c7, c11, 1
 	 */
 	cmp	r1, #0x1 		@ Check whether L2 inval is required
-	beq	omap3_do_wfi
+	beq	do_WFI
 
 clean_l2:
 	/*
@@ -282,7 +291,44 @@ clean_l2:
 	mov	lr, pc
 	bx	r1
 
-omap3_do_wfi:
+do_WFI:
+	ldr	r4, cm_clkstctrl_core	@ read the CLKSTCTRL_CORE
+	ldr	r5, [r4]		@ read the contents of CLKSTCTRL_CORE
+	and	r5, r5, #0x3
+	cmp	r5, #0x3
+	beq	omap3_do_wfi		@ Jumpt to SRAM function
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+
+	wfi				@ wait for interrupt
+
+	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+
+
+/*
+ * 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).
+ */
+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
@@ -302,7 +348,7 @@ omap3_do_wfi:
 
 /*
  * ===================================
- * == Resume path for non-OFF modes ==
+ * == Resume path for OFF/RET modes ==
  * ===================================
  */
 	nop
@@ -315,15 +361,113 @@ omap3_do_wfi:
 	nop
 	nop
 	nop
-	bl wait_sdrc_ok
+
+/*
+ * wait_sdrc_ok 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 SDRAM.
+ */
+
+/* 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]
+
+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 */
+wait_dll_lock_timed:
+	ldr	r4, wait_dll_lock_counter
+	add	r4, r4, #1
+	str	r4, wait_dll_lock_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, kick_counter
+	b	wait_dll_lock_timed
 
 /*
  * ===================================
- * == Exit point from non-OFF modes ==
+ * == Exit point from OFF/RET modes ==
  * ===================================
  */
+exit_nonoff_modes:
 	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_clkstctrl_core:
+	.word CM_CLKSTCTRL_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
+
 
 /*
  * ==============================
@@ -339,6 +483,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
@@ -357,7 +505,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
@@ -600,12 +749,41 @@ usettbr0:
  */
 	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
 ENTRY(es3_sdrc_fix)
 	ldr	r4, sdrc_syscfg		@ get config addr
@@ -634,6 +812,9 @@ ENTRY(es3_sdrc_fix)
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr
 
+/*
+ * Local variables
+ */
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
 sdrc_mr_0:
@@ -650,119 +831,3 @@ sdrc_manual_1:
 	.word	SDRC_MANUAL_1_P
 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]
-
-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 */
-wait_dll_lock_timed:
-	ldr	r4, wait_dll_lock_counter
-	add	r4, r4, #1
-	str	r4, wait_dll_lock_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, kick_counter
-	b	wait_dll_lock_timed
-
-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
-
-ENTRY(omap34xx_cpu_suspend_sz)
-	.word	. - omap34xx_cpu_suspend
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-02-04 11:39             ` Santosh Shilimkar
@ 2011-06-16 15:30               ` Pihet-XID, Jean
  2011-06-16 16:11                 ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Pihet-XID, Jean @ 2011-06-16 15:30 UTC (permalink / raw)
  To: Santosh Shilimkar, Cousson, Benoit, Kevin Hilman; +Cc: Jean Pihet, linux-omap

Hi Santosh, Benoit, Kevin,

I would like to revive this discussion. Can you give some feedback on
the self-refresh problem that is proposed in the latest patch from
Santosh? Cf. below for more details.

On Fri, Feb 4, 2011 at 12:39 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> Jean,
>> -----Original Message-----
>> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
>> Sent: Tuesday, February 01, 2011 5:01 PM
>> To: Jean Pihet
>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>
>> > -----Original Message-----
>> > From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
>> > Sent: Tuesday, February 01, 2011 4:53 PM
>> > To: Santosh Shilimkar
>> > Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>> > Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>> >
>>
>> [...]
>> > >> Does that makes sense?
>> > >>
>> > > Actually not. Rather I will separate only the scenario's
>> > > where CORE low power targets are attempted and only have
>> > > that code run from SRAM.
>> > >
>> > > There are scenario's where CORE can be active because MODEM,
>> > > DSP and MPU can still hit RET, OFF. And here, the errata
>> > > isn't applicable.
>> > >
>> > > Unless I missed something here, I think in the code we check
>> > > the the CORE attempted state and based on that we can do a
>> > > normal WFI from DDR (no self rfersh) or WFI from
>> > > SRAM with self refresh enabled.
>> > No. Only the MPU attempted state is checked (this actually is the
>> > 'save_state' parameter passed to omap_cpu_suspend).
>> > So it makes sense to check the CORE attempted state in order to
>> > decide
>> > to run the WFI from internal SRAM or DDR.
>> >
>> > The MPU attempted state is used to decide whether to save the
>> > MPU/L1/L2 context.
>> >
>> Looks like you miss-understood my point. As I understand from
>> errata, as long as core clock domain can idle with core
>> dpll divider auto idle enabled, the errata is applicable.
>>
>> So the only check needed is to see if the core clockdomain
>> hw_auto or sw sleep is enabled.
>>
>> If it is suppose to be not idle(we force few C-states
>> where CORE inactive is avoided for faster response),
>> we can execute WFI from DDR with not enabling
>> self refresh.
Is this the way to go?

>>
>> Rest of the scenario can follow the SRAM path.
>>
>> Hope this is clear to you.
>
> As per further discussion, I have updated your
> patch to address above by using core clockdomain
> state.
>
> Have tested OFF and RET with this new update and they
> work as expected. Feel free to update further if needed.
>
> ------
> From 49fe8164a40431807495638ec23639cc9bc53cb9 Mon Sep 17 00:00:00 2001
> From: Jean Pihet <j-pihet@ti.com>
> Date: Sat, 29 Jan 2011 20:51:19 +0530
> Subject: [PATCH] OMAP3: run the ASM sleep code from DDR
...

>
> -omap3_do_wfi:
> +do_WFI:
> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
> +       ldr     r5, [r4]                @ read the contents of
> CLKSTCTRL_CORE
> +       and     r5, r5, #0x3
> +       cmp     r5, #0x3
> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
> +       mov     r1, #0
> +       mcr     p15, 0, r1, c7, c10, 4
> +       mcr     p15, 0, r1, c7, c10, 5
> +
> +       wfi                             @ wait for interrupt
> +
> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return

This code has a few problems:
- there now are 2 wfi instructions, which I would like to avoid for
readability and maintainability,
- are the mcr instructions needed here? From
arch/arm/include/asm/system.h it seems those are not needed for
__LINUX_ARM_ARCH__ >= 7

Furthermore the main point of discussion to me is: is it advised to go
into wfi without self refresh requested? Can anyone confirm this?

> +
> +
> +/*
> + * 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).
> + */
> +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
> @@ -302,7 +348,7 @@ omap3_do_wfi:
>
>  /*
>  * ===================================
> - * == Resume path for non-OFF modes ==
> + * == Resume path for OFF/RET modes ==
>  * ===================================
>  */
>        nop
> @@ -315,15 +361,113 @@ omap3_do_wfi:
>        nop
>        nop
>        nop
> -       bl wait_sdrc_ok
...

Regards,
Jean
--
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] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-06-16 15:30               ` Pihet-XID, Jean
@ 2011-06-16 16:11                 ` Santosh Shilimkar
  2011-06-17  8:58                   ` Jean Pihet
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-06-16 16:11 UTC (permalink / raw)
  To: Pihet-XID, Jean; +Cc: Cousson, Benoit, Kevin Hilman, Jean Pihet, linux-omap

On 6/16/2011 9:00 PM, Pihet-XID, Jean wrote:
> Hi Santosh, Benoit, Kevin,
>
> I would like to revive this discussion. Can you give some feedback on
> the self-refresh problem that is proposed in the latest patch from
> Santosh? Cf. below for more details.
>
Comments below.

> On Fri, Feb 4, 2011 at 12:39 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com>  wrote:
>> Jean,
>>> -----Original Message-----
>>> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
>>> Sent: Tuesday, February 01, 2011 5:01 PM
>>> To: Jean Pihet
>>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>>> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>>
>>>> -----Original Message-----
>>>> From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
>>>> Sent: Tuesday, February 01, 2011 4:53 PM
>>>> To: Santosh Shilimkar
>>>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>>>> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>>>
>>>
>>> [...]
>>>>>> Does that makes sense?
>>>>>>
>>>>> Actually not. Rather I will separate only the scenario's
>>>>> where CORE low power targets are attempted and only have
>>>>> that code run from SRAM.
>>>>>
>>>>> There are scenario's where CORE can be active because MODEM,
>>>>> DSP and MPU can still hit RET, OFF. And here, the errata
>>>>> isn't applicable.
>>>>>
>>>>> Unless I missed something here, I think in the code we check
>>>>> the the CORE attempted state and based on that we can do a
>>>>> normal WFI from DDR (no self rfersh) or WFI from
>>>>> SRAM with self refresh enabled.
>>>> No. Only the MPU attempted state is checked (this actually is the
>>>> 'save_state' parameter passed to omap_cpu_suspend).
>>>> So it makes sense to check the CORE attempted state in order to
>>>> decide
>>>> to run the WFI from internal SRAM or DDR.
>>>>
>>>> The MPU attempted state is used to decide whether to save the
>>>> MPU/L1/L2 context.
>>>>
>>> Looks like you miss-understood my point. As I understand from
>>> errata, as long as core clock domain can idle with core
>>> dpll divider auto idle enabled, the errata is applicable.
>>>
>>> So the only check needed is to see if the core clockdomain
>>> hw_auto or sw sleep is enabled.
>>>
>>> If it is suppose to be not idle(we force few C-states
>>> where CORE inactive is avoided for faster response),
>>> we can execute WFI from DDR with not enabling
>>> self refresh.
> Is this the way to go?
>
I think so considering we need C-states for
faster responses as well.

>>>
>>> Rest of the scenario can follow the SRAM path.
>>>
>>> Hope this is clear to you.
>>
>> As per further discussion, I have updated your
>> patch to address above by using core clockdomain
>> state.
>>
>> Have tested OFF and RET with this new update and they
>> work as expected. Feel free to update further if needed.
>>
>> ------
>>  From 49fe8164a40431807495638ec23639cc9bc53cb9 Mon Sep 17 00:00:00 2001
>> From: Jean Pihet<j-pihet@ti.com>
>> Date: Sat, 29 Jan 2011 20:51:19 +0530
>> Subject: [PATCH] OMAP3: run the ASM sleep code from DDR
> ...
>
>>
>> -omap3_do_wfi:
>> +do_WFI:
>> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
>> +       ldr     r5, [r4]                @ read the contents of
>> CLKSTCTRL_CORE
>> +       and     r5, r5, #0x3
>> +       cmp     r5, #0x3
>> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
>> +       mov     r1, #0
>> +       mcr     p15, 0, r1, c7, c10, 4
>> +       mcr     p15, 0, r1, c7, c10, 5
>> +
>> +       wfi                             @ wait for interrupt
>> +
>> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
>
> This code has a few problems:
> - there now are 2 wfi instructions, which I would like to avoid for
> readability and maintainability,
> - are the mcr instructions needed here? From
> arch/arm/include/asm/system.h it seems those are not needed for
> __LINUX_ARM_ARCH__>= 7
The are barriers and in my clean-up I have already fixed them.
Your patch is bit old so has those things. Once you
refresh your patch against mainline, this can be simply
converted to DSB and DMB.

>
> Furthermore the main point of discussion to me is: is it advised to go
> into wfi without self refresh requested? Can anyone confirm this?
>
You can provided you ensure that CORE and SDRC can't idle.

I suggest you to create a patch against mainline and then we
take it from there.

Regards
Santosh

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-06-16 16:11                 ` Santosh Shilimkar
@ 2011-06-17  8:58                   ` Jean Pihet
  2011-06-17  9:13                     ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Jean Pihet @ 2011-06-17  8:58 UTC (permalink / raw)
  To: Santosh Shilimkar, Cousson, Benoit, Kevin Hilman; +Cc: linux-omap

Hi Santosh,

On Thu, Jun 16, 2011 at 6:11 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On 6/16/2011 9:00 PM, Pihet-XID, Jean wrote:
>>
>> Hi Santosh, Benoit, Kevin,
>>
>> I would like to revive this discussion. Can you give some feedback on
>> the self-refresh problem that is proposed in the latest patch from
>> Santosh? Cf. below for more details.
>>
> Comments below.
>
>> On Fri, Feb 4, 2011 at 12:39 PM, Santosh Shilimkar
>> <santosh.shilimkar@ti.com>  wrote:
>>>
>>> Jean,
>>>>
>>>> -----Original Message-----
>>>> From: Santosh Shilimkar [mailto:santosh.shilimkar@ti.com]
>>>> Sent: Tuesday, February 01, 2011 5:01 PM
>>>> To: Jean Pihet
>>>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>>>> Subject: RE: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>>>
>>>>> -----Original Message-----
>>>>> From: Jean Pihet [mailto:jean.pihet@newoldbits.com]
>>>>> Sent: Tuesday, February 01, 2011 4:53 PM
>>>>> To: Santosh Shilimkar
>>>>> Cc: linux-omap@vger.kernel.org; Jean Pihet-XID
>>>>> Subject: Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
>>>>>
>>>>
>>>> [...]
>>>>>>>
>>>>>>> Does that makes sense?
>>>>>>>
>>>>>> Actually not. Rather I will separate only the scenario's
>>>>>> where CORE low power targets are attempted and only have
>>>>>> that code run from SRAM.
>>>>>>
>>>>>> There are scenario's where CORE can be active because MODEM,
>>>>>> DSP and MPU can still hit RET, OFF. And here, the errata
>>>>>> isn't applicable.
>>>>>>
>>>>>> Unless I missed something here, I think in the code we check
>>>>>> the the CORE attempted state and based on that we can do a
>>>>>> normal WFI from DDR (no self rfersh) or WFI from
>>>>>> SRAM with self refresh enabled.
>>>>>
>>>>> No. Only the MPU attempted state is checked (this actually is the
>>>>> 'save_state' parameter passed to omap_cpu_suspend).
>>>>> So it makes sense to check the CORE attempted state in order to
>>>>> decide
>>>>> to run the WFI from internal SRAM or DDR.
>>>>>
>>>>> The MPU attempted state is used to decide whether to save the
>>>>> MPU/L1/L2 context.
>>>>>
>>>> Looks like you miss-understood my point. As I understand from
>>>> errata, as long as core clock domain can idle with core
>>>> dpll divider auto idle enabled, the errata is applicable.
>>>>
>>>> So the only check needed is to see if the core clockdomain
>>>> hw_auto or sw sleep is enabled.
>>>>
>>>> If it is suppose to be not idle(we force few C-states
>>>> where CORE inactive is avoided for faster response),
>>>> we can execute WFI from DDR with not enabling
>>>> self refresh.
>>
>> Is this the way to go?
>>
> I think so considering we need C-states for
> faster responses as well.
>
>>>>
>>>> Rest of the scenario can follow the SRAM path.
>>>>
>>>> Hope this is clear to you.
>>>
>>> As per further discussion, I have updated your
>>> patch to address above by using core clockdomain
>>> state.
>>>
>>> Have tested OFF and RET with this new update and they
>>> work as expected. Feel free to update further if needed.
>>>
>>> ------
>>>  From 49fe8164a40431807495638ec23639cc9bc53cb9 Mon Sep 17 00:00:00 2001
>>> From: Jean Pihet<j-pihet@ti.com>
>>> Date: Sat, 29 Jan 2011 20:51:19 +0530
>>> Subject: [PATCH] OMAP3: run the ASM sleep code from DDR
>>
>> ...
>>
>>>
>>> -omap3_do_wfi:
>>> +do_WFI:
>>> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
>>> +       ldr     r5, [r4]                @ read the contents of
>>> CLKSTCTRL_CORE
>>> +       and     r5, r5, #0x3
>>> +       cmp     r5, #0x3
>>> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
>>> +       mov     r1, #0
>>> +       mcr     p15, 0, r1, c7, c10, 4
>>> +       mcr     p15, 0, r1, c7, c10, 5
>>> +
>>> +       wfi                             @ wait for interrupt
>>> +
>>> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
>>
>> This code has a few problems:
>> - there now are 2 wfi instructions, which I would like to avoid for
>> readability and maintainability,
>> - are the mcr instructions needed here? From
>> arch/arm/include/asm/system.h it seems those are not needed for
>> __LINUX_ARM_ARCH__>= 7
>
> The are barriers and in my clean-up I have already fixed them.
> Your patch is bit old so has those things. Once you
> refresh your patch against mainline, this can be simply
> converted to DSB and DMB.
>
>>
>> Furthermore the main point of discussion to me is: is it advised to go
>> into wfi without self refresh requested? Can anyone confirm this?
>>
> You can provided you ensure that CORE and SDRC can't idle.
>
> I suggest you to create a patch against mainline and then we
> take it from there.

Re-pushed an updated patch on l-o ML: '[PATCH] OMAP3: run the ASM
sleep code from DDR'.

I deliberately omitted the code for WFI transition without
self-refresh because of the reasons mentioned here above and repeated
here (quoting myself):
"The DDR self refresh is enabled at each WFI but not necessarily hit.
It is actually triggered by the CORE idle request which depends on the
settings, the dependencies, the HW states... For example the CORE
state depends on the MPU state so if the MPU stays ON running
instructions the CORE will stay ON as well.

Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
already locked, e.g. if the CORE did not hit a low power state. Since
the actual CORE hit state is unknow after wake-up from WFI the
wait_sdrc_ok code always run at wake-up from MPU RET.
"

>
> Regards
> Santosh
>

Regards,
Jean
--
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] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-06-17  8:58                   ` Jean Pihet
@ 2011-06-17  9:13                     ` Santosh Shilimkar
  2011-06-17 15:59                       ` Kevin Hilman
  0 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2011-06-17  9:13 UTC (permalink / raw)
  To: Jean Pihet; +Cc: Cousson, Benoit, Kevin Hilman, linux-omap

On 6/17/2011 2:28 PM, Jean Pihet wrote:
> Hi Santosh,
>

[....]


>>>> -omap3_do_wfi:
>>>> +do_WFI:
>>>> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
>>>> +       ldr     r5, [r4]                @ read the contents of
>>>> CLKSTCTRL_CORE
>>>> +       and     r5, r5, #0x3
>>>> +       cmp     r5, #0x3
>>>> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
>>>> +       mov     r1, #0
>>>> +       mcr     p15, 0, r1, c7, c10, 4
>>>> +       mcr     p15, 0, r1, c7, c10, 5
>>>> +
>>>> +       wfi                             @ wait for interrupt
>>>> +
>>>> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
>>>

[....]

>>> Furthermore the main point of discussion to me is: is it advised to go
>>> into wfi without self refresh requested? Can anyone confirm this?
>>>
>> You can provided you ensure that CORE and SDRC can't idle.
>>
>> I suggest you to create a patch against mainline and then we
>> take it from there.
>
> Re-pushed an updated patch on l-o ML: '[PATCH] OMAP3: run the ASM
> sleep code from DDR'.
>
Thanks. We needed this to be in mainline.

> I deliberately omitted the code for WFI transition without
> self-refresh because of the reasons mentioned here above and repeated
> here (quoting myself):
> "The DDR self refresh is enabled at each WFI but not necessarily hit.
> It is actually triggered by the CORE idle request which depends on the
> settings, the dependencies, the HW states... For example the CORE
> state depends on the MPU state so if the MPU stays ON running
> instructions the CORE will stay ON as well.
>
> Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
> already locked, e.g. if the CORE did not hit a low power state. Since
> the actual CORE hit state is unknow after wake-up from WFI the
> wait_sdrc_ok code always run at wake-up from MPU RET.
> "
>
What is written here is completely right and I never said
anything against it. What I mentioned is if the CORE
clock-domain is under HW supervision, SDRC can idle
and hence the DDR can enter into self refresh.

Ofocurse on OMAP3 all clock-domain has static deps set
and hence above assumption is ok. The update I mentioned
in the code will make it complete even without auto-dep
assumption.

Anyways if that is the only point we are contesting, I
am OK to not have that change part of the patch because
it would work becasuse of auto-deps.

Regards
Santosh


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-06-17  9:13                     ` Santosh Shilimkar
@ 2011-06-17 15:59                       ` Kevin Hilman
  2011-06-17 16:50                         ` Santosh Shilimkar
  0 siblings, 1 reply; 17+ messages in thread
From: Kevin Hilman @ 2011-06-17 15:59 UTC (permalink / raw)
  To: Santosh Shilimkar; +Cc: Jean Pihet, Cousson, Benoit, linux-omap

Hi Santosh,

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On 6/17/2011 2:28 PM, Jean Pihet wrote:
>> Hi Santosh,
>>
>
> [....]
>
>
>>>>> -omap3_do_wfi:
>>>>> +do_WFI:
>>>>> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
>>>>> +       ldr     r5, [r4]                @ read the contents of
>>>>> CLKSTCTRL_CORE
>>>>> +       and     r5, r5, #0x3
>>>>> +       cmp     r5, #0x3
>>>>> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
>>>>> +       mov     r1, #0
>>>>> +       mcr     p15, 0, r1, c7, c10, 4
>>>>> +       mcr     p15, 0, r1, c7, c10, 5
>>>>> +
>>>>> +       wfi                             @ wait for interrupt
>>>>> +
>>>>> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
>>>>
>
> [....]
>
>>>> Furthermore the main point of discussion to me is: is it advised to go
>>>> into wfi without self refresh requested? Can anyone confirm this?
>>>>
>>> You can provided you ensure that CORE and SDRC can't idle.
>>>
>>> I suggest you to create a patch against mainline and then we
>>> take it from there.
>>
>> Re-pushed an updated patch on l-o ML: '[PATCH] OMAP3: run the ASM
>> sleep code from DDR'.
>>
> Thanks. We needed this to be in mainline.
>
>> I deliberately omitted the code for WFI transition without
>> self-refresh because of the reasons mentioned here above and repeated
>> here (quoting myself):
>> "The DDR self refresh is enabled at each WFI but not necessarily hit.
>> It is actually triggered by the CORE idle request which depends on the
>> settings, the dependencies, the HW states... For example the CORE
>> state depends on the MPU state so if the MPU stays ON running
>> instructions the CORE will stay ON as well.
>>
>> Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
>> already locked, e.g. if the CORE did not hit a low power state. Since
>> the actual CORE hit state is unknow after wake-up from WFI the
>> wait_sdrc_ok code always run at wake-up from MPU RET.
>> "
>>
> What is written here is completely right and I never said
> anything against it. What I mentioned is if the CORE
> clock-domain is under HW supervision, SDRC can idle
> and hence the DDR can enter into self refresh.
>
> Ofocurse on OMAP3 all clock-domain has static deps set
> and hence above assumption is ok. The update I mentioned
> in the code will make it complete even without auto-dep
> assumption.
>
> Anyways if that is the only point we are contesting, I
> am OK to not have that change part of the patch because
> it would work becasuse of auto-deps.

Sorry I haven't followed the whole thread...

Can you please clarify what would need to be updated if auto-deps were
removed?  We are hoping to remove them when we have full hwmod
conversion.

Kevin

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC/PATCH] OMAP3: run the ASM sleep code from DDR
  2011-06-17 15:59                       ` Kevin Hilman
@ 2011-06-17 16:50                         ` Santosh Shilimkar
  0 siblings, 0 replies; 17+ messages in thread
From: Santosh Shilimkar @ 2011-06-17 16:50 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Jean Pihet, Cousson, Benoit, linux-omap

On 6/17/2011 9:29 PM, Kevin Hilman wrote:
> Hi Santosh,
>
> Santosh Shilimkar<santosh.shilimkar@ti.com>  writes:
>
>> On 6/17/2011 2:28 PM, Jean Pihet wrote:
>>> Hi Santosh,
>>>
>>
>> [....]
>>
>>
>>>>>> -omap3_do_wfi:
>>>>>> +do_WFI:
>>>>>> +       ldr     r4, cm_clkstctrl_core   @ read the CLKSTCTRL_CORE
>>>>>> +       ldr     r5, [r4]                @ read the contents of
>>>>>> CLKSTCTRL_CORE
>>>>>> +       and     r5, r5, #0x3
>>>>>> +       cmp     r5, #0x3
>>>>>> +       beq     omap3_do_wfi            @ Jumpt to SRAM function
>>>>>> +       mov     r1, #0
>>>>>> +       mcr     p15, 0, r1, c7, c10, 4
>>>>>> +       mcr     p15, 0, r1, c7, c10, 5
>>>>>> +
>>>>>> +       wfi                             @ wait for interrupt
>>>>>> +
>>>>>> +       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
>>>>>
>>
>> [....]
>>
>>>>> Furthermore the main point of discussion to me is: is it advised to go
>>>>> into wfi without self refresh requested? Can anyone confirm this?
>>>>>
>>>> You can provided you ensure that CORE and SDRC can't idle.
>>>>
>>>> I suggest you to create a patch against mainline and then we
>>>> take it from there.
>>>
>>> Re-pushed an updated patch on l-o ML: '[PATCH] OMAP3: run the ASM
>>> sleep code from DDR'.
>>>
>> Thanks. We needed this to be in mainline.
>>
>>> I deliberately omitted the code for WFI transition without
>>> self-refresh because of the reasons mentioned here above and repeated
>>> here (quoting myself):
>>> "The DDR self refresh is enabled at each WFI but not necessarily hit.
>>> It is actually triggered by the CORE idle request which depends on the
>>> settings, the dependencies, the HW states... For example the CORE
>>> state depends on the MPU state so if the MPU stays ON running
>>> instructions the CORE will stay ON as well.
>>>
>>> Also the code in wait_sdrc_ok will exit quicker if the CORE DPLL is
>>> already locked, e.g. if the CORE did not hit a low power state. Since
>>> the actual CORE hit state is unknow after wake-up from WFI the
>>> wait_sdrc_ok code always run at wake-up from MPU RET.
>>> "
>>>
>> What is written here is completely right and I never said
>> anything against it. What I mentioned is if the CORE
>> clock-domain is under HW supervision, SDRC can idle
>> and hence the DDR can enter into self refresh.
>>
>> Ofocurse on OMAP3 all clock-domain has static deps set
>> and hence above assumption is ok. The update I mentioned
>> in the code will make it complete even without auto-dep
>> assumption.
>>
>> Anyways if that is the only point we are contesting, I
>> am OK to not have that change part of the patch because
>> it would work becasuse of auto-deps.
>
> Sorry I haven't followed the whole thread...
>
> Can you please clarify what would need to be updated if auto-deps were
> removed?  We are hoping to remove them when we have full hwmod
> conversion.
>
Sure.
I sent an update on Jean's original patch to check the CORE clock
domain state(HW_SUP or SW_WKUP). If we are in HW_SUP and the SDRC
self refresh bit enabled, SDRC can idle along with CORE. So
in that case and _only_ that case we need to execute WFI from
SRAM. I thought that's a right way to go and not depend on
auto-deps.

Jean in his refreshed patch dropped that update
with above auto-dep reasoning. For sure, with autodep
set, we won't need that additional logic because
CORE CD can never IDLE without MPU CD being in idle.

Regards
Santosh

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2011-06-17 16:50 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-13 16:19 [RFC/PATCH] OMAP3: run the ASM sleep code from DDR jean.pihet
2011-01-24 14:29 ` Jean Pihet
2011-01-27 10:13   ` Vishwanath Sripathy
2011-01-27 13:50     ` Jean Pihet
2011-01-29 17:14 ` Santosh Shilimkar
2011-01-30  5:57   ` Santosh Shilimkar
2011-01-31 10:36     ` Jean Pihet
2011-01-31 11:00       ` Santosh Shilimkar
2011-02-01 11:23         ` Jean Pihet
2011-02-01 11:31           ` Santosh Shilimkar
2011-02-04 11:39             ` Santosh Shilimkar
2011-06-16 15:30               ` Pihet-XID, Jean
2011-06-16 16:11                 ` Santosh Shilimkar
2011-06-17  8:58                   ` Jean Pihet
2011-06-17  9:13                     ` Santosh Shilimkar
2011-06-17 15:59                       ` Kevin Hilman
2011-06-17 16:50                         ` Santosh Shilimkar

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.