⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xllp_suspendresumea.s

📁 Intel PXA270底层设备驱动代码
💻 S
字号:
;******************************************************************************
;
;  COPYRIGHT (C) 2002-2005 Intel Corporation.
;
;  This software as well as the software described in it is furnished under 
;  license and may only be used or copied in accordance with the terms of the 
;  license. The information in this file is furnished for informational use 
;  only, is subject to change without notice, and should not be construed as 
;  a commitment by Intel Corporation. Intel Corporation assumes no 
;  responsibility or liability for any errors or inaccuracies that may appear 
;  in this document or any software that may be provided in association with 
;  this document.
; 
;  Except as permitted by such license, no part of this document may be 
;  reproduced, stored in a retrieval system, or transmitted in any form or by 
;  any means without the express written consent of Intel Corporation. 
;
;******************************************************************************
; PURPOSE:
;     Suspend/Resume functions linked into the OS kernel.
;
; NOTES:
;
; Conext:
; These functions assume that the MMU is enabled, the stack is valid, and CPU is in a priveledged mode.
; These functions are linked into the OS kernel. They are not linked into the boot loaders.
;
; Resume phases:
; These are a fabrication that have no direct basis in hardware, but help understanding of the resume process.
;
; Resume phase 1 puts the CPU and the platform in a known (default) working state.
; It is performed by the low level boot code.
;
; Phase 2 restores virtual addressing, the CPU core mode, and the stack for that mode.
; Phase 2 resume data therefore consists of data that is needed on resume to...
;     1. Restore the MMU.
;     2. Restore the CPU core to the mode it was in just before power off.
;     3. Restore the stack pointer for the restored CPU mode.
;
; Resume phase 3 (and beyond) restores other CPU and platform state.
;
; The routines in this file are used to save state prior to suspend and 
; begin phase 3 of the resume (ie. restore current CPU mode registers).
; Phase 2 resume is performed in another module linked into the boot loader.
; 
;**************************************************************************************************
        INCLUDE  xllp_ARM_macros.inc                    ; for RETURN macro
        INCLUDE  xllp_ResumePhase2_Data.inc             ; definition of ResumePhase2 data area
        INCLUDE  xlli_Bulverde_defs.inc                 ; Bulverde specific include file
;
        AREA    |.text|, CODE, READONLY, ALIGN=5        ; Align =5 required for "ALIGN 32" to work
;
; Functions made public by this file:
;
        EXPORT Xllp_SuspendAndResumeA
        EXPORT Xllp_SaveMMU
        EXPORT Xllp_SaveMSARMRegs
        EXPORT Xllp_RestoreMSARMRegs
		
; External functions we need        
        IMPORT Xllp_SimpleChecksum
        IMPORT OSD_CacheFlush
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Xllp_SaveMSARMRegs and Xllp_RestoreMSARMRegs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mode specific (MS) ARM registers are are saved and restored by the following functions.
; For all modes other than FIQ mode, 'mode specific' means SP, LR, and SPSR.
; R8-R12 are specific to FIQ mode but are common to all other modes.
; This is described in the ARM Architecture Reference Manual.
;
; Registers common to all modes are not saved and restored by these functions.
; It is left to the calling routine to save and restore the common registers.
;
; A 'pseudo-stack' is used to save the registers.
; The term 'pseudo-stack' is used because the customary stmdb and ldmia register saving instructions are used. 
; However, since SP itself is mode specific, the current stack is not used.
; Previous counterparts of this code used the current stack for each mode as the save area.
; The approach used here means that we don't care what modes actually have their SP setup.
; All that matters is that the current mode stack is valid.
; This approach is likely to work with different operating systems regardless of what modes they use.
;

; R0 = pseudo-stack pointer (updated on return)
; R1 = mode
Xllp_SaveMSARMRegs FUNCTION
    stmdb   sp!, {r1-r7,lr}            ; Save registers we may use (except r0)
    
    mov     r4, r0                     ; setup pseudo stack pointer
    and     r1, r1, #(xlli_CPSR_Mode_MASK) ; get mode only
    
    mrs     r0, cpsr
	mov		r2, r0                     ; save cpsr to restore before returning
    
    bic     r0, r0, #(xlli_CPSR_Mode_MASK)
	orr		r0, r0, #(xlli_CPSR_I_Bit:OR:xlli_CPSR_F_Bit) ; no interrupts
    orr     r0, r0, r1                 ; Set requested mode
    msr     cpsr, r0

    ; SYS mode doesn't have an SPSR
    cmp     r1, #xlli_CPSR_Mode_SYS
    mrsne   r0, spsr
    cmp     r1, #xlli_CPSR_Mode_FIQ
    stmeqdb r4!, {r0,r8-r12,sp,lr}     ; Save SPSR, r8-r12, SP, LR, for FIQ mode
    stmnedb r4!, {r0,sp,lr}            ; Save SPSR, SP, LR, for other requested mode

    msr		cpsr, r2                   ; restore cpsr - return to previous mode
    
    mov		r0, r4                     ; return final address
    ldmia   sp!, {r1-r7,lr}            ; restore registers we may have used

    RETURN
	ENDFUNC

; R0 = pseudo-stack pointer (updated on return)
; R1 = mode
Xllp_RestoreMSARMRegs FUNCTION
    stmdb   sp!, {r1-r7,lr}            ; Save registers we may use (except r0)
    
    mov     r4, r0                     ; setup pseudo stack pointer
    and     r1, r1, #(xlli_CPSR_Mode_MASK) ; mode bits only
    
    mrs     r0, cpsr
	mov		r2, r0                     ; save cpsr to restore before returning
    
    bic     r0, r0, #(xlli_CPSR_Mode_MASK)
	orr		r0, r0, #(xlli_CPSR_I_Bit:OR:xlli_CPSR_F_Bit) ; no interrupts
    orr     r0, r0, r1                 ; Set requested mode
    msr     cpsr, r0

    cmp     r1, #xlli_CPSR_Mode_FIQ
    ldmeqia   r4!, {r0,r8-r12,sp,lr}   ; Restore SPSR, r8-r12, SP, LR, for FIQ mode
    ldmneia r4!, {r0,sp,lr}            ; Restore SPSR, SP, LR, for other requested mode
    ; SYS mode doesn't have an SPSR
    cmp     r1, #xlli_CPSR_Mode_SYS
    msrne   spsr, r0
	
    msr		cpsr, r2                   ; return to previous mode

    mov		r0, r4                     ; return final address
    ldmia   sp!, {r1-r7,lr}            ; restore registers we may have used
    
    RETURN
	ENDFUNC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This function saves the various MMU registers.
; Restore of the MMU is done in Xllp_ResumePhase2A (which is linked into the boot loaders).
; r0 = address of MMU save area
Xllp_SaveMMU   FUNCTION
    stmdb   sp!, {r1-r7,lr}     ; Save regs we may use

    ; Save argument to free up r0
    mov     r5, r0 

        ; Cp15_ACR_MMU
    mrc     p15, 0, r0, c1, c0, 0           ; load r0 with MMU Control
    ;ldr     r1, =XLLP_CP15_ACR_MMU_VLD_MSK  ; mask off the undefined bits
    ;and     r0, r0, r1
    str     r0, [r5, #RESUMEPHASE2_CP15_ACR_MMU_OFFSET]   ; store MMU Control data

        ; Cp15_AUXCR_MMU;   // cp15 Reg1:1: assume restored elsewhere.
    mrc     p15, 0, r0, c1, c1, 0           ; load r0 with MMU Aux Control
    ;ldr     r1, =XLLP_CP15_AUXCR_MMU_VLD_MSK  ; mask off the undefined bits
    ;and     r0, r0, r1
    str     r0, [r5, #RESUMEPHASE2_CP15_AUXCR_MMU_OFFSET] ; store MMU Aux Control data

        ; Cp15_TTBR_MMU;    // cp15 Reg2:0
    mrc     p15, 0, r0, c2, c0, 0           ; load r0 with TTB address.
    ;ldr     r1, =XLLP_CP15_TTBR_MMU_VLD_MSK  ; mask off the undefined bits
    ;and     r0, r0, r1
    str     r0, [r5, #RESUMEPHASE2_CP15_TTBR_MMU_OFFSET] ; store TTB address

        ; Cp15_DACR_MMU;    // cp15 Reg3:0, all bits valid
    mrc     p15, 0, r0, c3, c0, 0           ; load r0 with domain access control.
    str     r0, [r5, #RESUMEPHASE2_CP15_DACR_MMU_OFFSET] ; store domain access control

        ; Cp15_PID_MMU;              // cp15 Reg13; Assume set by OS if used.
    mrc     p15, 0, r0, c13, c0, 0          ; load r0 with PID.
    ;ldr     r1, =XLLP_CP15_PID_MMU_VLD_MSK  ; mask off the undefined bits
    ;and     r0, r0, r1
    str     r0, [r5, #RESUMEPHASE2_CP15_PID_MMU_OFFSET] ; store PID

    ldmia   sp!, {r1-r7,lr}     ; Restore regs we may have used
    RETURN

    ENDFUNC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     
; This is the function that actually powers the system off.
; r0 = address of suspend save area
Xllp_SuspendAndResumeA   FUNCTION
    ; Save current mode registers on the current mode stack.
    stmdb   sp!, {r0-r12,lr}
    
    ; Move parameter to free up r0
    mov     r5, r0 
    
    ; Save the SP
    ; This is the value that should be restored on resume before jumping to XllpResume below
    str     sp, [r5, #RESUMEPHASE2_SP_OFFSET]

    ; Save CPSR
    mrs     r3, cpsr
    str     r3, [r5, #RESUMEPHASE2_CPSR_OFFSET]

    ; Save Coprocessor Access Register
    mrc     p15, 0, r0, c15, c1, 0
    str     r0, [r5, #RESUMEPHASE2_CPAR_OFFSET]
    
    ; Save the resume address
    add     r0, pc, #XllpResumePhase3 - (. + 8)
    str     r0, [r5, #RESUMEPHASE2_RESUMEPHASE3_PC_OFFSET]
    
    ; Save the MMU
    mov     r0, r5
    bl      Xllp_SaveMMU
    
    ; Store word and checksum (word count is included in checksum)
    mov     r1, #RESUMEPHASE2_DATA_WORDS
    str     r1, [r5, #RESUMEPHASE2_WORDCOUNT_OFFSET]
    add     r0, r5, #RESUMEPHASE2_WORDCOUNT_OFFSET
    bl      Xllp_SimpleChecksum
    str     r0, [r5, #RESUMEPHASE2_CHECKSUM_OFFSET]
    
    ; At this point all state has been saved.
    ; The cache and write buffers need to be flushed before power down.
    ; Cache flushing is OS dependent, so OSD_CacheFlush needs to be provided for each OS environment.
    ; It must simply ensure that all cached and buffered data has been written back to memory.
    stmdb   sp!, {lr}
    bl      OSD_CacheFlush
    ldmia   sp!, {lr}
    nop
    nop
    nop
    nop

;================================================================    
XllpEnterSleepMode
;================================================================    
    ldr r3, =(xlli_PWRMODE_SLEEP)
    b   %F1                                         ; Purely precautionary, in case we needed to clear pipeline
    ALIGN  32
1
    mcr     p14, 0, r3, c7, c0, 0                   ; Enter sleep

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
;================================================================    
XllpResumePhase3
;================================================================    
    ; This is where we should end up here when we resume.
    ; The MMU, CPU mode, and stack should have been restored at this point so 
    ; adrresses should be virtual and the stack should look as it did when we saved the SP above
    ; All that remains to be done here is to restore the current mode registers.
    ldmia   sp!, {r0-r12,lr}
    RETURN
    ENDFUNC
;**************************************************************************************************
    END
  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -