fw.s
; Data Cache Characteristics.
;
DCACHE_LINES_PER_SET_BITS EQU 6
DCACHE_LINES_PER_SET EQU 64
DCACHE_NUM_SETS EQU 8
DCACHE_SET_INDEX_BIT EQU (32 - DCACHE_LINES_PER_SET_BITS)
DCACHE_LINE_SIZE EQU 32
SLEEPDATA_BASE_VIRTUAL EQU 0xac058000 ; keep in sync w/ config.bib
SLEEPDATA_BASE_PHYSICAL EQU 0x3c058000
;**
; * CPUPowerOff - OFF button handler(Called from OEMPowerOff() in cfw.c)
; * This routine is invoked when the OFF button is pressed. It is responsible
; * for any final power off state and putting the cpu into standby.
; *
; * Entry none
; * Exit none
; * Uses r0-r3
; *
LEAF_ENTRY CPUPowerOff
; 1. Save register state and return address on the stack.
;
stmdb sp!, {r4-r12}
stmdb sp!, {lr}
; b .
; 2. Save MMU & CPU Registers to RAM.
;
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; base of Sleep mode storage
ldr r2, =Awake_address
str r2, [r3], #4 ; save resume function address (virtual).
mrc p15, 0, r2, c1, c0, 0
ldr r0, =MMU_CTL_MASK
bic r2, r2, r0
str r2, [r3], #4 ; save MMU control data.
mrc p15, 0, r2, c2, c0, 0
ldr r0, =MMU_TTB_MASK
bic r2, r2, r0
str r2, [r3], #4 ; save TTB address.
mrc p15, 0, r2, c3, c0, 0
str r2, [r3], #4 ; save domain access control.
str sp, [r3], #4 ; save SVC mode stack pointer.
mrs r2, spsr
str r2, [r3], #4 ; save SVC status register.
mov r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; enter FIQ mode, no interrupts.
msr cpsr, r1
mrs r2, spsr
stmia r3!, {r2, r8-r12, sp, lr} ; save the FIQ mode registers.
mov r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; enter ABT mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the ABT mode Registers.
mov r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; enter IRQ mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the IRQ Mode Registers.
mov r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; enter UND mode, no interrupts.
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr} ; save the UND mode Registers.
mov r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; enter SYS mode, no interrupts.
msr cpsr, r1
stmia r3!, {sp, lr} ; save the SYS mode Registers.
mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; back to SVC mode, no interrupts.
msr cpsr, r1
; 3. Compute the checksum on SleepData (verify integrity of data after resume).
;
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; get pointer to SLEEPDATA.
mov r2, #0
ldr r0, =(SLEEPDATA_SIZE-1) ; get size of data structure (in words).
30
ldr r1, [r3], #4 ; compute the checksum.
and r1, r1, #0x1
mov r1, r1, LSL #31
orr r1, r1, r1, LSR #1
add r2, r2, r1
subs r0, r0, #1
bne %b30
ldr r0, =vGPIOBASE
str r2, [r0, #oGSTATUS3] ; save the checksum in the Power Manager Scratch pad register.
; 4. Mask and clear all interrupts.
;
ldr r0, =vINTBASE
mvn r2, #0
str r2, [r0, #oINTMSK]
str r2, [r0, #oSRCPND]
str r2, [r0, #oINTPND]
; 5. Flush caches and TLBs.
;
bl ARMClearUTLB
bl ARMFlushICache
ldr r0, = (DCACHE_LINES_PER_SET - 1)
ldr r1, = (DCACHE_NUM_SETS - 1)
ldr r2, = DCACHE_SET_INDEX_BIT
ldr r3, = DCACHE_LINE_SIZE
bl ARMFlushDCache
; 6. Set external wake-up interrupts (EINT0-2: power-button and keyboard).
;
ldr r0, =vGPIOBASE
ldr r1, =0x550a
str r1, [r0, #oGPFCON]
; ldr r1, =0x55550100
; str r1, [r0, #oGPGCON]
; 7. Switch to power-off mode.
;
ldr r0, =vMISCCR ; hit the TLB
ldr r0, [r0]
ldr r0, =vCLKCON
ldr r0, [r0]
; **These registers are used later during power-off.
;
ldr r0, =vREFRESH
ldr r1, [r0] ; r1 = rREFRESH.
orr r1, r1, #(1 << 22)
; **These registers are used later during power-off.
;
ldr r2, =vMISCCR
ldr r3, [r2]
orr r3, r3, #(7 << 17) ; make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up.
; **These registers are used later during power-off.
;
ldr r4, =vCLKCON
ldr r5, =0x7fff8 ; power-off mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WinCE 3.00 assembler has some problem about ALIGN instruction.
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.
; If the rom is EBOOT, the target address is 0x92001004.
; Else if the rom is NAND, the target address is 0x92000004.
; ldr r8, =0xEA000000
; add r8, r8, #0x3f0
; add r8, r8, #0xe ; make value to 0xEA0003FE
; ldr r6, =0x92000000 ; make address to 0x9200 1004 or 0x9200 0004
; ldr r7, [r6] ; Check ROM Address data, if 0xEA0003FE, it is EBOOT
; cmp r7, r8
; bne %f50
; add r6, r6, #0x1000 ; Because eboot startup code is located at 0x1000.
;50
; add r6, r6, #0x4 ;
; mov pc, r6 ; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
b SelfRefreshAndPowerOff
ALIGN 32 ; for I-Cache Line(32Byte, 8 Word)
SelfRefreshAndPowerOff ; run with Instruction Cache's code
str r1, [r0] ; Enable SDRAM self-refresh
str r3, [r2] ; MISCCR Setting
str r5, [r4] ; Power Off !!
b .
; This point is called from EBOOT's startup code(MMU is enabled)
; in this routine, left information(REGs, INTMSK, INTSUBMSK ...)
Awake_address
; 1. Recover CPU Registers
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; Sleep mode information data structure
add r2, r3, #SleepState_FIQ_SPSR
mov r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr r8, [r2], #4
ldr r9, [r2], #4
ldr r10, [r2], #4
ldr r11, [r2], #4
ldr r12, [r2], #4
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
mov r1, #Mode_ABT:OR:I_Bit ; Enter ABT mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
mov r1, #Mode_IRQ:OR:I_Bit ; Enter IRQ mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
mov r1, #Mode_UND:OR:I_Bit ; Enter UND mode, no interrupts
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
; mov r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
mov r1, #Mode_SYS:OR:I_Bit ; Enter SYS mode, no interrupts
msr cpsr, r1
ldr sp, [r2], #4
ldr lr, [r2]
; mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Enter SVC mode, no interrupts
mov r1, #Mode_SVC:OR:I_Bit ; Enter SVC mode, no interrupts
msr cpsr, r1
ldr r0, [r3, #SleepState_SVC_SPSR]
msr spsr, r0
; 2. Recover Last mode's REG's, & go back to caller of CPUPowerOff()
ldr sp, [r3, #SleepState_SVC_SP]
ldr lr, [sp], #4
ldmia sp!, {r4-r12}
mov pc, lr ; and now back to our sponsors
;
; MMU_WaitForInterrupt() from 2410slib.s (in bsp/others/test2410_r11 dirs)
;
;void MMU_WaitForInterrupt(void)
EXPORT MMU_WaitForInterrupt
MMU_WaitForInterrupt
mcr p15,0,r0,c7,c0,4
mov pc, lr ;MOV_PC_LR
END
复制代码