📄 pmgrxsc1.s
字号:
; do Checksum on the Sleepdata
; ldr r0, =(0x44440011)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x100 ; just a marker
ldr r3, =(SLEEPDATA_BASE_VIRTUAL) ; get pointer to SLEEPDATA
ldr r0, =(SLEEP_CHECKSUM_SEED) ; Use the non-zero seed.
; Force bad checksum for testing
; ldr r0, =(0x0) ; Pick a non-zero seed.
; get size of data structure (in words)
ldr r2, =(SLEEPDATA_SIZE-1) ; but skip checksum record.
30
ldr r1, [r3], #4
add r0, r0, r1
mov r0, r0, ROR #31
subs r2, r2, #1
bne %b30
IF Interworking :LOR: Thumbing
bx lr
ELSE
mov pc, lr ; return
ENDIF
;; End of PwrMgrGetSleepDataCksm()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Go to sleeeep, my ba-a-by...
;; This is a really long lullaby.
;;
LEAF_ENTRY OEMPowerOff
IF :DEF: TEST_STUB_PWR_OFF
; For preliminary module testing.
IF Interworking :LOR: Thumbing
bx lr
ELSE
mov pc, lr ; return
ENDIF
ENDIF; :DEF: TEST_STUB_PWR_OFF
PmgrContextSave
;; Assume only a trusted mode. Save state
stmdb sp!, {r0-r12,lr} ; Push entry mode state onto our stack
; Use r7 as write pointer because any "C" subroutines will preserve it.
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_ENTRY_CPSR)
mrs r3, cpsr
mrs r2, spsr
str r3, [r7], #4 ; store entry mode CPSR
str lr, [r7], #4 ; store entry mode return address
str sp, [r7], #4 ; store entry mode stack pointer
str r2, [r7], #4 ; store entry mode SPSR
; ldr r0, =(0x55550011)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; Enter and save SVC mode state.
bic r3, r3, #(CPSR_Mode_MASK:OR:I_Bit:OR:F_Bit)
orr r3, r3, #CPSR_Mode_SVC:OR:I_Bit:OR:F_Bit ; Enter SVC mode, no interrupts
msr cpsr_c, r3 ; Only interested in control fields
; Push SVC state onto our stack
stmdb sp!, {r8-r12,lr} ; Save R8 and up, in case entry mode was FIQ
;ldr r0, =(0x33330022)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
mrs r2, spsr
str r2, [r7], #4 ; store SVC status register
str sp, [r7], #4 ; store SVC stack pointer
str lr, [r7], #4 ; store SVC return address
; UINT32 sleepDataSize; // debug info only
ldr r2, =SLEEPDATA_SIZE
str r2, [r7], #4 ; store SVC status register
; UINT32 awakeAddr; // Virtual address of wakeup code
ldr r2, =(PmgrResume) ; store Virtual return address
str r2, [r7], #4
;ldr r0, =(0x33330033)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; UINT32 mmuCtl; // cp15 Reg1:0: assume restored elsewhere.
mrc p15, 0, r2, c1, c0, 0 ; load r2 with MMU Control
ldr r0, =MMU_CTL_MASK ; mask off the undefined bits
bic r2, r2, r0
str r2, [r7], #4 ; store MMU Control data
; UINT32 mmuAuxCtl; // cp15 Reg1:1: assume restored elsewhere.
mrc p15, 0, r2, c1, c1, 0 ; load r2 with MMU Aux Control
ldr r0, =MMU_AUX_CTL_MASK ; mask off the undefined bits
bic r2, r2, r0
str r2, [r7], #4 ; store MMU Aux Control data
; UINT32 mmuTtbAddr; // cp15 Reg2:0
mrc p15, 0, r2, c2, c0, 0 ; load r2 with TTB address.
ldr r0, =MMU_TTB_MASK ; mask off the undefined bits
bic r2, r2, r0
str r2, [r7], #4 ; store TTB address
; UINT32 domainAccessCtl; // cp15 Reg3:0
mrc p15, 0, r2, c3, c0, 0 ; load r2 with domain access control.
str r2, [r7], #4 ; store domain access control
; UINT32 pid; // cp15 Reg13; Assume set by OS if used.
mrc p15, 0, r2, c13, c0, 0 ; load r2 with PID.
str r2, [r7], #4 ; store PID
;ldr r0, =(0x33330044)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; UINT32 cp15BreakPoint[5]; // Save / restore meaningful??
; Access Instruction
mrc p15, 0, r2, c14, c8, 0 ; load r2 with IBCR0
str r2, [r7], #4 ; store IBCR0
mrc p15, 0, r2, c14, c9, 0 ; load r2 with IBCR1
str r2, [r7], #4 ; store IBCR1
mrc p15, 0, r2, c14, c0, 0 ; load r2 with DBR0
str r2, [r7], #4 ; store DBR0
mrc p15, 0, r2, c14, c3, 0 ; load r2 with DBR1
str r2, [r7], #4 ; store DBR1
mrc p15, 0, r2, c14, c4, 0 ; load r2 with DBCON
str r2, [r7], #4 ; store DBCON
;
; Save Coprocessor Access Register value before modifying to get CP0
; UINT32 cpAccessReg; // cp15 Reg15
mrc p15, 0, r2, c15, c1, 0 ; load r2 with Coprocessor Access Register.
str r2, [r7], #4 ; store Coprocessor Access Register
;ldr r0, =(0x33330055)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
IF :DEF: USING_COPROCSUPPORT
; Subroutine symbol defined only under this flag.
mov r0, r7
bl XSC1GetCP0Acc ; Uses R0..R3, returns results in 8-byte buffer pointed to by R0.
ENDIF; :DEF: USING_COPROCSUPPORT
; Reestablish write pointer into table.
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_CP14_R0)
; Get 7 registers at a time.
mrc p14, 0, r0, c0, c0, 0 ; p14:0
mrc p14, 0, r1, c1, c0, 0 ; p14:1
mrc p14, 0, r2, c2, c0, 0 ; p14:2
mrc p14, 0, r3, c3, c0, 0 ; p14:3
; p14:4,5 are reserved
mrc p14, 0, r4, c6, c0, 0 ; p14:6
mrc p14, 0, r5, c7, c0, 0 ; p14:7
mrc p14, 0, r6, c8, c0, 0 ; p14:8
stmia r7!, {r0-r6} ; Store in memory
mrc p14, 0, r0, c9, c0, 0 ; p14:9
mrc p14, 0, r1, c10, c0, 0 ; p14:10
mrc p14, 0, r2, c11, c0, 0 ; p14:11
mrc p14, 0, r3, c12, c0, 0 ; p14:12
mrc p14, 0, r4, c13, c0, 0 ; p14:13
mrc p14, 0, r5, c14, c0, 0 ; p14:14
mrc p14, 0, r6, c15, c0, 0 ; p14:15
stmia r7!, {r0-r6} ; Store in memory
;ldr r0, =(0x33330066)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; UINT32 Cccr [1]; // Core Clock Configuration Register
ldr r3, =CCCR_BASE_U_VIRTUAL ; xsc1.inc has the address constant
GET_CCCR r0, r3, r2 ; r0 gets the value from CCCR
str r0, [r7], #4 ; Store CCCR
; // Note: OSCC not saved because 32KHz oscillator is known to be in use.
; // For FIQ, put Saved PSR into r2 and save r2,r8..12, sp and lr)
; UINT32 fiqModeRegs [8];
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
mrs r2, spsr
stmia r7!, {r2, r8-r12, sp, lr} ; store the FIQ mode registers
;ldr r0, =(0x33330077)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // For ABT, put Spsr into r0 and save r0, sp and lr)
; UINT32 abtModeRegs [3];
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
mrs r0, spsr
stmia r7!, {r0, sp, lr} ; store the ABT mode Registers
; ldr r0, =(0x33330088)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // For IRQ, put Spsr into r0 and save r0, sp and lr)
; UINT32 irqModeRegs [3];
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
mrs r0, spsr
stmia r7!, {r0, sp, lr} ; store the IRQ Mode Registers
; ldr r0, =(0x33330099)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // For UND, put Spsr into r0 and save r0, sp and lr)
; UINT32 undModeRegs [3];
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
mrs r0, spsr
stmia r7!, {r0, sp, lr} ; store the UND mode Registers
; ldr r0, =(0x333300AA)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // For SYS, save sp and lr; no SPSR in SYS mode
; UINT32 sysModeRegs [2];
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
stmia r7!, {sp, lr} ; store the SYS mode Registers
; ldr r0, =(0x333300BB)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
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 r0, =(0x333300CC)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; Peripheral clocks (CKEN)
ldr r6, =(CKEN_BASE_U_VIRTUAL)
ldr r0, [r6]
ldr r1, =(CKEN_VALID_MASK)
and r0, r0, r1 ; clear out undefined bits
str r0, [r7], #4 ; store current peripheral clock enables
IF PLAT_LUBBOCK = "1"
IF :DEF: TEST_SHOW_CKEN
ldr r1, =(FPGA_REGS_BASE_U_VIRTUAL)
str r0, [r1, #HEXLED_OFFSET]
ldr r1, =(0x10000000)
19
subs r1, r1, #1
bne %B19
ENDIF; :DEF: TEST_SHOW_CKEN
ENDIF; PLAT_LUBBOCK = "1"
; Store GPIO registers
ldr r6, =(GPIO_BASE_U_VIRTUAL) ; GPLRs start at GPIO base
ldmia r6!, {r0-r2} ; Get the three GPLRs into registers
stmia r7!, {r0-r2} ; Store GPLRs
; GPDRs immediately follow GPLRs
ldmia r6!, {r0-r2} ; Get the three GPDRs into registers
stmia r7!, {r0-r2} ; Store GPDRs
ldr r6, =(GPIO_BASE_U_VIRTUAL+GRER_x_OFFSET) ; Old symbol for GRER0
ldmia r6!, {r0-r2} ; Get the three GRERs into registers
stmia r7!, {r0-r2} ; Store GRERs
; Note: in target processor, GFERs immediately follow GRERs
ldmia r6!, {r0-r2} ; Get the three GFERs into registers
stmia r7!, {r0-r2} ; Store GFERs
ldr r6, =(GPIO_BASE_U_VIRTUAL+GAFR0_x_OFFSET)
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_GAFR_0_L)
ldmia r6!, {r0-r5} ; Get the six GAFRs into registers
stmia r7!, {r0-r5} ; Store GAFRs
; ldr r0, =(0x333300DD)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // OS timer regs: match registers and others
; // OSCR, OSSR, OWER, OIER
ldr r6, =(OST_BASE_U_VIRTUAL)
ldmia r6!, {r0-r3} ; Get the four match register values
stmia r7!, {r0-r3} ; Store match registers
ldmia r6!, {r0-r3} ; Get OSCR, OSSR, OWER, OIER values
stmia r7!, {r0-r3} ; Store OSCR, OSSR, OWER, OIER
; // RTC info: the RTC keeps running while we sleep, so this
; is just for reference. It won't be restored.
ldr r6, =RTC_BASE_U_VIRTUAL
ldmia r6!, {r0-r3} ; Get the four RTC register values
stmia r7!, {r0-r3} ; Store RTC registers
IF :DEF: TEST_CLEARING_RTC_INTS
; Clear and retrigger any pending RTC interrupts
; Don't mask-disable them, though. Keep them available for wake-up.
ldr r6, =(RTC_BASE_U_VIRTUAL+RTSR_OFFSET)
ldr r0, [r6]
orr r0, r0, #(RTC_AL|RTC_HZ) ; Set bits to clear clock ints
str r0, [r6] ; Clear Clock Interrupt Sources
ENDIF; :DEF: TEST_CLEARING_RTC_INTS
; ldr r0, =(0x333300E0)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; // Interrupt Controller
ldr r6, =ICMR_BASE_U_VIRTUAL
ldr r0, [r6]
str r0, [r7], #4 ; store ICMR
IF :DEF: TEST_MASK_OFF_ALL_ICMR
mov r0, #0
str r0, [r6] ; mask-disable all interrupts
ENDIF; :DEF: TEST_MASK_OFF_ALL_ICMR
ldr r6, =ICCR_BASE_U_VIRTUAL
ldr r0, [r6]
str r0, [r7], #4 ; store ICCR
; ldr r0, =(0x333300E1)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
; IF PLAT_LUBBOCK = "1"
; ldr r6, =(FPGA_REGS_BASE_U_VIRTUAL) ; XSC1BD Board registers base
;
; ldr r0, [r6, #HEXLED_OFFSET] ; get hex LED values
; ldr r1, [r6, #BLANKLED_OFFSET] ; get enable state of all LEDs
; ldr r2, [r6, #MISC_WR_OFFSET] ; get Misc. Write Reg settings
; ldr r3, [r6, #INT_MASK_OFFSET] ; get mask settings for board-level interrupt controller
; stmia r7!, {r0-r3} ; Store the four FPGA settings
;
; IF :DEF: TEST_SHUTTING_DOWN_FPGA
; mov r0, #0
; str r0, [r6, #INT_MASK_OFFSET] ;Mask disable all interrupts
;
; ENDIF; :DEF: TEST_SHUTTING_DOWN_FPGA
; ENDIF; PLAT_LUBBOCK = "1"
; ldr r0, =(0x333300E2)
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000
;; Non-restored, informational save
; // Same as stored in Power Manager Scratch pad
; UINT32 checksum; // register
bl PwrMgrGetSleepDataCksm ; Checksum returned in R0
ldr r7, =(SLEEPDATA_BASE_VIRTUAL+SleepState_CHKSUM)
str r0, [r7] ; Store in sleep data area
ldr r2, =(PSPR_BASE_U_VIRTUAL)
str r0, [r2] ; Store in Power Manager Scratch pad register
IF :DEF: TEST_SHOW_CKSM
ldr r3, =(0x333300FF) ; tiptoe around the checksum
VIRT_HEX_DISP_REG_NOT_R1 r3, 0x10000000
VIRT_HEX_DISP_REG_NOT_R1 r0, 0x10000000 ; checksum
ENDIF; :DEF: TEST_SHOW_CKSM
; How many NOPs do we really need here - any?
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
IF :DEF: REAL_NOT_ONLY_REG_SAVE_RSTR
;;;;;;;;;;;;;;;; Finished saving state.
;;;;;;;;;;;;;;;; Now shut down.
; /* Need to determine HOW to find out what the sleep mode levels for output lines
; should be.
; Set up the PGSRs so that they put the desired values onto the
; GPIO output pins during sleep mode.
; Get memory bases for Power Mgr and GPIO areas
ldr r5, =(PWR_BASE_U_VIRTUAL)
; Current values for PGSRs are hard-coded. They may want to become programmatic.
ldr r0, =(PMGR_PGSR0_SET_MASK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -