📄 pmgrxsc1.s
字号:
str r0, [r5, #PGSR_x_OFFSET] ; Set high and low values to be used in sleep
ldr r0, =(PMGR_PGSR1_SET_MASK)
str r0, [r5, #PGSR_y_OFFSET] ; Set high and low values to be used in sleep
ldr r0, =(PMGR_PGSR2_SET_MASK)
str r0, [r5, #PGSR_z_OFFSET] ; Set high and low values to be used in sleep
; ldr r0, =(0x88880349)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; Move on to the rest of the Power Manager unit configuration
ldr r0, =(PMGR_PCFR_VAL) ; When sleeping: Disable 32MHz osc, force PCMCIA and nCS lines
str r0, [r5, #PCFR_OFFSET] ; Tell the Pwr Mgr hardware about these choices.
ldr r6, =(GPIO_BASE_U_VIRTUAL)
IF :DEF: TEST_FORCING_GPIO1_WAKEUP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Special test values forcing wakeup via GP1
; // Set up GPIO_1 as an input. GPIO going LOW (noDOT) will put us to sleep.
; v_pGPIOReg->GPDR_x &= 0xFFFFFFFD;
ldr r0, [r6, #GPDR_x_OFFSET] ; Get current low direction reg
mov r1, #2 ; mask for GPIO1
bic r0, r0, r1 ; force GPIO1 as input
str r0, [r6, #GPDR_x_OFFSET] ; tell the hardware
; // Enable GPIO_1 to wake up from sleep
mov r0, #0x2
; Now, enable the wake up reasons in the power manager.
str r0, [r5, #PWER_OFFSET]
; // Enable Rising edge to wake ONLY (no falling edge)
mov r0, #0x2
str r0, [r5, #PRER_OFFSET]
; No falling edge wakes (as in GPIO_0
mov r0, #0x0
str r0, [r5, #PFER_OFFSET]
;; End of Special test values forcing wakeup via GP1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ELSE; IF :DEF: TEST_FORCING_GPIO1_WAKEUP
;; Standard issue code here.
; SetRisingEdgeGpioTriggers(); // GPIO 1
ldr r0, =(PMGR_PRER_BITS) ; Rising edge GPIOs (only 0..15 possible)
str r0, [r5, #PRER_OFFSET]
; SetFallingEdgeGpioTriggers();
ldr r0, =(PMGR_PFER_BITS) ; Falling edge GPIOs (only 0..15 possible)
str r0, [r5, #PFER_OFFSET]
; SetPowerManagerWakeUpEnables(); // FIRST CUT: RTC, GPIO 0 AND 1 ONLY FOR WAKEUP.
; Put wakeup reasons in R0
IF :DEF: TEST_WAKE_SKIP_RTC
; All wakeup GPIOs ORed together, without the RTC, are the wakeup sources
ldr r0, =(PMGR_PRER_BITS:OR:PMGR_PFER_BITS)
ELSE ; IF :DEF: TEST_WAKE_SKIP_RTC
; All wakeup GPIOs ORed together, plus the RTC, are the wakeup sources
ldr r0, =(PMGR_PRER_BITS:OR:PMGR_PFER_BITS:OR:PMGR_PWER_WERTC)
ENDIF ; ELSE of IF :DEF: TEST_WAKE_SKIP_RTC
; Now, enable the wake up reasons in the power manager.
str r0, [r5, #PWER_OFFSET]
ENDIF; ELSE :DEF: TEST_FORCING_GPIO1_WAKEUP
IF :DEF: DOING_SLEEP_MEDIATED_SOFT_RESET
ldr r1, =(SLEEPDATA_BASE_VIRTUAL+SleepState_SLEEP_TYPE)
ldr r1, [r1]
cmp r1, #SLEEP_TYPE_SOFT_RESET
bne notSLEEP_TYPE_SOFT_RESET
bl PmAutoWakeupSoftReset
notSLEEP_TYPE_SOFT_RESET
ENDIF ; :DEF: DOING_SLEEP_MEDIATED_SOFT_RESET
IF :DEF: TEST_SR_AUTO_REPEAT
;; Testing. Wake up in n seconds.
bl PmAutoWakeupRepTest
;; End Testing wake up in n seconds
ENDIF ; :DEF: TEST_SR_AUTO_REPEAT
;; With the Lubbock board, auto wakeup can be set at run time with Switch 17=no-dot.
; IF PLAT_LUBBOCK = "1"
; ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
; GET_S17 r0, r1
; ands r0, r0, r0
; bne doneAutoWakeup ; non-zero is dot position, skip auto-wakeup
; ;; Testing. Wake up in n seconds.
; bl PmAutoWakeupRepTest
; ;; End Testing wake up in n seconds
;
;doneAutoWakeup
; ENDIF ; PLAT_LUBBOCK = "1"
; ldr r0, =(0x88880350)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
IF :DEF: REAL_RESTORING_GPIOS
; ClearPendingGpioWakeupInterrupts();
ldr r0, =(PWER_GPIO_BITS) ; Get clear mask (all possible sources)
str r0, [r6, #GEDR_x_OFFSET] ; Clear any possible current GPIO based reasons for an exit from sleep
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Registers all saved by now.
; ldr r0, =(0x88880400)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
ENDIF; :DEF: REAL_RESTORING_GPIOS
IF :DEF: TEST_SR_AUTO_REPEAT
; Currently, don't count iterations unless in test mode.
ldr r1, =(SLEEPDATA_BASE_VIRTUAL+SleepState_IterationCounter)
ldr r0, [r1]
add r0, r0, #1
str r0, [r1]
IF :DEF: PLAT_LUBBOCK
; Now, show the information
ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
str r0, [r1, #HEXLED_OFFSET]
ENDIF ; :DEF: PLAT_LUBBOCK
ENDIF ; :DEF: TEST_SR_AUTO_REPEAT
IF :DEF: REAL_FLUSH_DATA_CACHE
;
; bl FlushDCache ; R0, R1, R2 undefined, that's OK
; Need to substitute inline code for a call to the subroutine
; - So copy the active ingredients right here.
DCACHE_CACHELINECOUNT EQU 1024
MINIDCACHE_CACHELINECOUNT EQU 64
CACHELINESIZE EQU 32
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 ; Drain the Write Buffer
MOV R1, #DCACHE_CACHELINECOUNT
LDR R0, =ZBANK_BASE_C_VIRTUAL
; ** DCache Flush **
44
mcr p15, 0, r0, c7, c2, 5 ; Allocate a line at the virtual address ZBANK_BASE_C_VIRTUAL
; (tossing out a dirty line back to memory)
mcr p15, 0, r0, c7, c6, 1 ; Invalidate the same cache-line
ADD R0, R0, #CACHELINESIZE ; Increment the address in R0 to the next cache line
SUBS R1, R1, #1 ; Decrement loop count
BNE %B44
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 ; Drain the Write Buffer
;
; Deal with Sighting #22271: Drain write buffer may be ignored if no outstanding memory requests
; exist within the core.
;
; I will deal with this by doing an arbitrary read from c=b=0 space (i.e. uncached, nonbuffered)
;
ldr r0, =BOOT_FLASH_BASE_U_VIRTUAL
ldr r1, [r0] ; read MDCNFG
;; End of inline version of FlushDCache
; MiniData cache not supported in Windows* CE as of 10/23/2001
ENDIF; :DEF: REAL_FLUSH_DATA_CACHE
;;
;;
;; WARNING: NO DATA MAY BE SAVED AFTER THIS POINT BECAUSE THE VIRTUAL ADDRESS USED HERE IS NOT AN
;; UNCACHED MAPPING. IT SHOULD BE ASSUMED THAT ANY DATA WRITTEN AFTER THIS WILL BE
;; LOST DURING SLEEP
;;
;;
; // Board level register: LEDs off; assume the drivers
; TurnOffBoardLEDs(); // did the other board controls appropriately.
; IF PLAT_LUBBOCK = "1"
;
; IF :DEF: TEST_SHOW_LEDS
; ldr r0, =(0x88880444)
; VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; ELSE ; TEST_SHOW_LEDS
; ; This does not touch LEDs D2 or D3, which are controlled through the UCB1400.
; ; It is assumed that a UCB1400 module will save and restore information about
; ; all settings for that device.
; ldr r0, =(0x0000FFFF) ; All 1s in defined positions
; ldr r6, =(FPGA_REGS_BASE_U_VIRTUAL+BLANKLED_OFFSET)
; str r0, [r6] ; Set all bits to turn off LEDs
; ENDIF
;
; ENDIF ; PLAT_LUBBOCK
ldr r0, =(0) ; Turn off all CKEN before sleep.
ldr r1, =(CKEN_BASE_U_VIRTUAL)
str r0, [r1]
IF :DEF: TEST_NOT_REALLY_SLEEPING
; ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
; mov r0, #0
; str r0, [r1, #BLANKLED_OFFSET] ; Enable all LEDs
; ldr r0, =(0x88880446)
; ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
; str r0, [r1, #HEXLED_OFFSET]
ldr r1, =(0x10000000)
19
subs r1, r1, #1
bne %B19
b PmgrResume
ENDIF; :DEF: TEST_NOT_REALLY_SLEEPING
; Delay for serial debug output
; ldr r1, =(DEBUGPRINT_SLEEPDELAY_CNT+1)
;19
; subs r1, r1, #1
; bne %B19
ldr r2, =(PWRMODE_SLEEP)
IF B_STEP_PXA2X0 = "1"
;;;;;;;;;;;;;;;;;;;;;;
;; Sighting 28071
;;
;; Workaround includes modification to force execution from cache and disable MMU
;; Values to place SDRAM into self-refresh manually
ldr r4, =(MDREFR_BASE_U_VIRTUAL)
ldr r5, [r4, #0x0]
orr r5, r5, #0x00400000
;; Do dummy read from address 0 - set up address in r3
ldr r3, =(BOOT_FLASH_BASE_U_VIRTUAL)
b PmgrAfterAlign ; Skip over any filler before ALIGN directive
ALIGN 32
PmgrAfterAlign
; all values are now in registers. These last instructions should be in
; instruction cache at this time.
str r5, [r4, #0x0] ; Put SDRAM into self-refresh
ldr r1, [r3] ; force address lines low, reading from 0x00
ENDIF ; B_STEP_PXA2X0 = "1"
;;
;; End Sighting 28071
;;;;;;;;;;;;;;;;;;;;;;
MCR p14, 0, r2, c7, c0, 0 ;; Write to coprocessor, and sleep
nop
nop
nop
nop
nop
nop
nop
nop
;;
;'''''''''''''''''''''''''''''''''''''''
;------------------------------------------------------------------------
; We are now down (and should never get here ...)
; IF PLAT_LUBBOCK = "1"
;
; ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
; mov r0, #0
; str r0, [r1, #BLANKLED_OFFSET] ; Enable all LEDs
; ldr r0, =(0x88880666) ; Failure code for non-sleeping
; str r0, [r1, #HEXLED_OFFSET]
; IF :DEF: TEST_SR_AUTO_REPEAT
; ; optionally here, overwrite normal LED to keep the counter showing
; ldr r1, =(SLEEPDATA_BASE_VIRTUAL+SleepState_IterationCounter)
; ldr r0, [r1]
; str r0, [r6, #HEXLED_OFFSET]
; ENDIF ; :DEF: TEST_SR_AUTO_REPEAT
;
; ENDIF; :DEF: PLAT_LUBBOCK
87
b %B87 ; don't let it fall through
ELSE ; IF :DEF: REAL_NOT_ONLY_REG_SAVE_RSTR
b PmgrResume
ENDIF; :DEF: REAL_NOT_ONLY_REG_SAVE_RSTR
;; End of OEMPowerOff()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; PmgrResume ()
;;
LEAF_ENTRY PmgrResume
; ldr r0, =(0x22220011)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; - Restore registers for all processor modes except SVC, entry and USR
; SleepState_FIQ
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_FIQ_SPSR) ; base of FIQ data storage
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
; ldr r0, =(0x22220022)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x04000000
ldr r0, [r7], #4
msr spsr_cxsf, r0
ldmia r7!, {r8-r12, sp, lr} ; load the FIQ mode registers (already got spsr)
; SleepState_ABT
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
; ldr r0, =(0x22220033)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x4000000
ldr r0, [r7], #4
msr spsr_cxsf, r0
ldmia r7!, {sp, lr} ; load the ABT mode registers (already got spsr)
; SleepState_IRQ
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
; ldr r0, =(0x22220044)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x4000000
ldr r0, [r7], #4
msr spsr_cxsf, r0
ldmia r7!, {sp, lr} ; load the IRQ mode registers (already got spsr)
;SleepState_UND
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
; ldr r0, =(0x22220055)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x4000000
ldr r0, [r7], #4
msr spsr_cxsf, r0
ldmia r7!, {sp, lr} ; load the UND mode registers (already got spsr)
;SleepState_SYS
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
; ldr r0, =(0x22220066)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x4000000
ldmia r7!, {sp, lr} ; load the SYS mode registers
; Use the SVC mode and its stack for most stuff.
mrs r0, cpsr
bic r0, r0, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r0, r0, #CPSR_Mode_SVC:OR:I_Bit:OR:F_Bit ; Enter SVC mode, no interrupts
msr cpsr_c, r0 ; Only interested in control fields
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_SVC_SP)
ldr sp, [r7]
; peripheral clocks (CKEN)
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_CKEN)
ldr r6, =(CKEN_BASE_U_VIRTUAL)
ldmia r7!, {r0} ; Get the stored clock enables
str r0, [r6] ; Restore previous peripheral clocks
; - Restore GPIO states
; - Set output levels (multi-step process)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -