[PATCH 5/7] OMAP3: rework of the ASM sleep code execution paths
Santosh Shilimkar
santosh.shilimkar at ti.com
Fri Dec 17 05:37:15 EST 2010
> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> owner at vger.kernel.org] On Behalf Of jean.pihet at newoldbits.com
> Sent: Friday, December 17, 2010 3:38 PM
> To: linux-omap at vger.kernel.org
> Cc: khilman at deeprootsystems.com; linux-arm-kernel at lists.infradead.org;
> Jean Pihet
> Subject: [PATCH 5/7] OMAP3: rework of the ASM sleep code execution paths
>
> From: Jean Pihet <j-pihet at ti.com>
>
> - Reworked and simplified the execution paths for better
> readability and to avoid duplication of code,
> - Added comments on the entry and exit points and the interaction
> with the ROM code for OFF mode restore,
> - Reworked the existing comments for better readability.
>
> Tested on N900 and Beagleboard with full RET and OFF modes,
> using cpuidle and suspend.
>
> Signed-off-by: Jean Pihet <j-pihet at ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar at ti.com>
> ---
> arch/arm/mach-omap2/control.c | 9 +-
> arch/arm/mach-omap2/sleep34xx.S | 313
+++++++++++++++++++++++-----------
> -----
> 2 files changed, 191 insertions(+), 131 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/control.c
b/arch/arm/mach-omap2/control.c
> index 728f268..f4b19ed 100644
> --- a/arch/arm/mach-omap2/control.c
> +++ b/arch/arm/mach-omap2/control.c
> @@ -239,7 +239,14 @@ void omap3_save_scratchpad_contents(void)
> struct omap3_scratchpad_prcm_block prcm_block_contents;
> struct omap3_scratchpad_sdrc_block sdrc_block_contents;
>
> - /* Populate the Scratchpad contents */
> + /*
> + * Populate the Scratchpad contents
> + *
> + * The "get_*restore_pointer" functions are used to provide a
> + * physical restore address where the ROM code jumps while waking
> + * up from MPU OFF/OSWR state.
> + * The restore pointer is stored into the scratchpad.
> + */
> scratchpad_contents.boot_config_ptr = 0x0;
> if (cpu_is_omap3630())
> scratchpad_contents.public_restore_ptr =
> diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-
> omap2/sleep34xx.S
> index beeb682..12061fd 100644
> --- a/arch/arm/mach-omap2/sleep34xx.S
> +++ b/arch/arm/mach-omap2/sleep34xx.S
> @@ -71,6 +71,13 @@
> * API functions
> */
>
> +/*
> + * The "get_*restore_pointer" functions are used to provide a
> + * physical restore address where the ROM code jumps while waking
> + * up from MPU OFF/OSWR state.
> + * The restore pointer is stored into the scratchpad.
> + */
> +
> .text
> /* Function call to get the restore pointer for resume from OFF */
> ENTRY(get_restore_pointer)
> @@ -102,7 +109,7 @@ ENTRY(get_es3_restore_pointer_sz)
> /*
> * L2 cache needs to be toggled for stable OFF mode functionality on
3630.
> * This function sets up a flag that will allow for this toggling to
take
> - * place on 3630. Hopefully some version in the future maynot need this
> + * place on 3630. Hopefully some version in the future may not need
this.
> */
> ENTRY(enable_omap3630_toggle_l2_on_restore)
> stmfd sp!, {lr} @ save registers on stack
> @@ -144,34 +151,158 @@ ENTRY(save_secure_ram_context_sz)
> .word . - save_secure_ram_context
>
> /*
> + * ======================
> + * == Idle entry point ==
> + * ======================
> + */
> +
> +/*
> * Forces OMAP into idle state
> *
> - * omap34xx_suspend() - This bit of code just executes the WFI
> - * for normal idles.
> + * omap34xx_suspend() - This bit of code saves the CPU context if
needed
> + * and executes the WFI instruction
> *
> - * Note: This code get's copied to internal SRAM at boot. When the OMAP
> - * wakes up it continues execution at the point it went to sleep.
> + * Notes:
> + * - this code gets copied to internal SRAM at boot.
> + * - 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.
> */
> ENTRY(omap34xx_cpu_suspend)
> stmfd sp!, {r0-r12, lr} @ save registers on stack
>
> - /* r0 contains restore pointer in sdram */
> - /* r1 contains information about saving context */
> - 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
> - str r5, [r4] @ write back to SDRC_POWER
register
> + /*
> + * r0 contains restore pointer in sdram
> + * r1 contains information about saving context:
> + * 0 - No context lost
> + * 1 - Only L1 and logic lost
> + * 2 - Only L2 lost
> + * 3 - Both L1 and L2 lost
> + */
>
> + /* Save context only if required */
> cmp r1, #0x0
> - /* If context save is required, do that and execute wfi */
> - bne save_context_wfi
> + beq omap3_do_wfi
> +
> +save_context_wfi:
> + mov r8, r0 @ Store SDRAM address in r8
> + mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
> + mov r4, #0x1 @ Number of parameters for restore
call
> + stmia r8!, {r4-r5} @ Push parameters for restore call
> + mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
> + stmia r8!, {r4-r5} @ Push parameters for restore call
> +
> + /* Check what that target sleep state is from r1 */
> + cmp r1, #0x2 @ Only L2 lost, no need to save
context
> + beq clean_caches
> +
> +l1_logic_lost:
> + /* Store sp and spsr to SDRAM */
> + mov r4, sp
> + mrs r5, spsr
> + mov r6, lr
> + stmia r8!, {r4-r6}
> + /* Save all ARM registers */
> + /* Coprocessor access control register */
> + mrc p15, 0, r6, c1, c0, 2
> + stmia r8!, {r6}
> + /* TTBR0, TTBR1 and Translation table base control */
> + mrc p15, 0, r4, c2, c0, 0
> + mrc p15, 0, r5, c2, c0, 1
> + mrc p15, 0, r6, c2, c0, 2
> + stmia r8!, {r4-r6}
> + /*
> + * Domain access control register, data fault status register,
> + * and instruction fault status register
> + */
> + mrc p15, 0, r4, c3, c0, 0
> + mrc p15, 0, r5, c5, c0, 0
> + mrc p15, 0, r6, c5, c0, 1
> + stmia r8!, {r4-r6}
> + /*
> + * Data aux fault status register, instruction aux fault status,
> + * data fault address register and instruction fault address
> register
> + */
> + mrc p15, 0, r4, c5, c1, 0
> + mrc p15, 0, r5, c5, c1, 1
> + mrc p15, 0, r6, c6, c0, 0
> + mrc p15, 0, r7, c6, c0, 2
> + stmia r8!, {r4-r7}
> + /*
> + * user r/w thread and process ID, user r/o thread and process ID,
> + * priv only thread and process ID, cache size selection
> + */
> + mrc p15, 0, r4, c13, c0, 2
> + mrc p15, 0, r5, c13, c0, 3
> + mrc p15, 0, r6, c13, c0, 4
> + mrc p15, 2, r7, c0, c0, 0
> + stmia r8!, {r4-r7}
> + /* Data TLB lockdown, instruction TLB lockdown registers */
> + mrc p15, 0, r5, c10, c0, 0
> + mrc p15, 0, r6, c10, c0, 1
> + stmia r8!, {r5-r6}
> + /* Secure or non secure vector base address, FCSE PID, Context
PID*/
> + mrc p15, 0, r4, c12, c0, 0
> + mrc p15, 0, r5, c13, c0, 0
> + mrc p15, 0, r6, c13, c0, 1
> + stmia r8!, {r4-r6}
> + /* Primary remap, normal remap registers */
> + mrc p15, 0, r4, c10, c2, 0
> + mrc p15, 0, r5, c10, c2, 1
> + stmia r8!,{r4-r5}
> +
> + /* Store current cpsr*/
> + mrs r2, cpsr
> + stmia r8!, {r2}
> +
> + mrc p15, 0, r4, c1, c0, 0
> + /* save control register */
> + stmia r8!, {r4}
> +
> +clean_caches:
> + /*
> + * Clean Data or unified cache to POU
> + * How to invalidate only L1 cache???? - #FIX_ME#
> + * mcr p15, 0, r11, c7, c11, 1
> + */
> + cmp r1, #0x1 @ Check whether L2 inval is
required
> + beq omap3_do_wfi
> +
> +clean_l2:
> + /*
> + * jump out to kernel flush routine
> + * - reuse that code is better
> + * - it executes in a cached space so is faster than refetch per-
> block
> + * - should be faster and will change with kernel
> + * - 'might' have to copy address, load and jump to it
> + */
> + ldr r1, kernel_flush
> + mov lr, pc
> + bx r1
> +
> +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
> + str r5, [r4] @ write back to SDRC_POWER
register
> +
> /* Data memory barrier and Data sync barrier */
> mov r1, #0
> mcr p15, 0, r1, c7, c10, 4
> mcr p15, 0, r1, c7, c10, 5
>
> +/*
> + * ===================================
> + * == WFI instruction => Enter idle ==
> + * ===================================
> + */
> wfi @ wait for interrupt
>
> +/*
> + * ===================================
> + * == Resume path for non-OFF modes ==
> + * ===================================
> + */
> nop
> nop
> nop
> @@ -184,7 +315,29 @@ ENTRY(omap34xx_cpu_suspend)
> nop
> bl wait_sdrc_ok
>
> - ldmfd sp!, {r0-r12, pc} @ restore regs and return
> +/*
> + * ===================================
> + * == Exit point from non-OFF modes ==
> + * ===================================
> + */
> + ldmfd sp!, {r0-r12, pc} @ restore regs and return
> +
> +
> +/*
> + * ==============================
> + * == Resume path for OFF mode ==
> + * ==============================
> + */
> +
> +/*
> + * The restore_* functions are called by the ROM code
> + * when back from WFI in OFF mode.
> + * Cf. the get_*restore_pointer functions.
> + *
> + * restore_es3: applies to 34xx >= ES3.0
> + * restore_3630: applies to 36xx
> + * restore: common code for 3xxx
> + */
> restore_es3:
> ldr r5, pm_prepwstst_core_p
> ldr r4, [r5]
> @@ -214,12 +367,17 @@ restore_3630:
> ldr r1, control_mem_rta
> mov r2, #OMAP36XX_RTA_DISABLE
> str r2, [r1]
> - /* Fall thru for the remaining logic */
> +
> + /* Fall thru to common code for the remaining logic */
> +
> restore:
> - /* Check what was the reason for mpu reset and store the reason
> in r9*/
> - /* 1 - Only L1 and logic lost */
> - /* 2 - Only L2 lost - In this case, we wont be here */
> - /* 3 - Both L1 and L2 lost */
> + /*
> + * Check what was the reason for mpu reset and store the reason in
> r9:
> + * 0 - No context lost
> + * 1 - Only L1 and logic lost
> + * 2 - Only L2 lost - In this case, we wont be here
> + * 3 - Both L1 and L2 lost
> + */
> ldr r1, pm_pwstctrl_mpu
> ldr r2, [r1]
> and r2, r2, #0x3
> @@ -422,118 +580,12 @@ usettbr0:
> and r4, r2
> mcr p15, 0, r4, c1, c0, 0
>
> +/*
> + * ==============================
> + * == Exit point from OFF mode ==
> + * ==============================
> + */
> ldmfd sp!, {r0-r12, pc} @ restore regs and return
> -save_context_wfi:
> - mov r8, r0 /* Store SDRAM address in r8 */
> - mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register
> - mov r4, #0x1 @ Number of parameters for restore
call
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> - mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register
> - stmia r8!, {r4-r5} @ Push parameters for restore call
> - /* Check what that target sleep state is:stored in r1*/
> - /* 1 - Only L1 and logic lost */
> - /* 2 - Only L2 lost */
> - /* 3 - Both L1 and L2 lost */
> - cmp r1, #0x2 /* Only L2 lost */
> - beq clean_l2
> - cmp r1, #0x1 /* L2 retained */
> - /* r9 stores whether to clean L2 or not*/
> - moveq r9, #0x0 /* Dont Clean L2 */
> - movne r9, #0x1 /* Clean L2 */
> -l1_logic_lost:
> - /* Store sp and spsr to SDRAM */
> - mov r4, sp
> - mrs r5, spsr
> - mov r6, lr
> - stmia r8!, {r4-r6}
> - /* Save all ARM registers */
> - /* Coprocessor access control register */
> - mrc p15, 0, r6, c1, c0, 2
> - stmia r8!, {r6}
> - /* TTBR0, TTBR1 and Translation table base control */
> - mrc p15, 0, r4, c2, c0, 0
> - mrc p15, 0, r5, c2, c0, 1
> - mrc p15, 0, r6, c2, c0, 2
> - stmia r8!, {r4-r6}
> - /* Domain access control register, data fault status register,
> - and instruction fault status register */
> - mrc p15, 0, r4, c3, c0, 0
> - mrc p15, 0, r5, c5, c0, 0
> - mrc p15, 0, r6, c5, c0, 1
> - stmia r8!, {r4-r6}
> - /* Data aux fault status register, instruction aux fault status,
> - datat fault address register and instruction fault address
> register*/
> - mrc p15, 0, r4, c5, c1, 0
> - mrc p15, 0, r5, c5, c1, 1
> - mrc p15, 0, r6, c6, c0, 0
> - mrc p15, 0, r7, c6, c0, 2
> - stmia r8!, {r4-r7}
> - /* user r/w thread and process ID, user r/o thread and process ID,
> - priv only thread and process ID, cache size selection */
> - mrc p15, 0, r4, c13, c0, 2
> - mrc p15, 0, r5, c13, c0, 3
> - mrc p15, 0, r6, c13, c0, 4
> - mrc p15, 2, r7, c0, c0, 0
> - stmia r8!, {r4-r7}
> - /* Data TLB lockdown, instruction TLB lockdown registers */
> - mrc p15, 0, r5, c10, c0, 0
> - mrc p15, 0, r6, c10, c0, 1
> - stmia r8!, {r5-r6}
> - /* Secure or non secure vector base address, FCSE PID, Context
PID*/
> - mrc p15, 0, r4, c12, c0, 0
> - mrc p15, 0, r5, c13, c0, 0
> - mrc p15, 0, r6, c13, c0, 1
> - stmia r8!, {r4-r6}
> - /* Primary remap, normal remap registers */
> - mrc p15, 0, r4, c10, c2, 0
> - mrc p15, 0, r5, c10, c2, 1
> - stmia r8!,{r4-r5}
> -
> - /* Store current cpsr*/
> - mrs r2, cpsr
> - stmia r8!, {r2}
> -
> - mrc p15, 0, r4, c1, c0, 0
> - /* save control register */
> - stmia r8!, {r4}
> -clean_caches:
> - /* Clean Data or unified cache to POU*/
> - /* How to invalidate only L1 cache???? - #FIX_ME# */
> - /* mcr p15, 0, r11, c7, c11, 1 */
> - cmp r9, #1 /* Check whether L2 inval is required or not*/
> - bne skip_l2_inval
> -clean_l2:
> - /*
> - * Jump out to kernel flush routine
> - * - reuse that code is better
> - * - it executes in a cached space so is faster than refetch per-
> block
> - * - should be faster and will change with kernel
> - * - 'might' have to copy address, load and jump to it
> - */
> - ldr r1, kernel_flush
> - mov lr, pc
> - bx r1
> -
> -skip_l2_inval:
> - /* Data memory barrier and Data sync barrier */
> - mov r1, #0
> - mcr p15, 0, r1, c7, c10, 4
> - mcr p15, 0, r1, c7, c10, 5
> -
> - wfi @ wait for interrupt
> - nop
> - nop
> - nop
> - nop
> - nop
> - nop
> - nop
> - nop
> - nop
> - nop
> - bl wait_sdrc_ok
> - /* restore regs and return */
> - ldmfd sp!, {r0-r12, pc}
>
>
> /*
> @@ -683,5 +735,6 @@ kick_counter:
> .word 0
> wait_dll_lock_counter:
> .word 0
> +
> ENTRY(omap34xx_cpu_suspend_sz)
> .word . - omap34xx_cpu_suspend
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the linux-arm-kernel
mailing list