📄 pmgr1110.s
字号:
; TITLE("SA11X0 Firmware Initialization")
;++
;
; Copyright (c) 1999 Intel Corporation
;
;--
OPT 2 ; disable listing
INCLUDE kxarm.h
INCLUDE sa11x0.inc
INCLUDE sa11x0BD.inc
INCLUDE sa11x1.inc
;OPT 128 ; disable listing of macro expansions
OPT 1 ; reenable listing
;TEST_LCD_DELAY EQU 1 ; Insert 20 ms delay in shutdown
;TEST_DISABLE_INTERRUPT EQU 1 ; Disable interrupts before shutdown
TEST_DISABLE_DMA EQU 1 ; Disable DMA before shutdown
;TEST_DISABLE_LCD EQU 1 ; Disable LCD before shutdown
TEST_EARLY_STOP_CBR EQU 1 ; Stop CBR before cache sweep
TEST_PRESTOP_CBR EQU 1 ; Stop CBR and wait
TEST_DMA_SYNC EQU 1 ; Sync with running DMA
TEST_SW_SHUTDOWN EQU 1 ; Use S/W shutdown method
;TEST_TRACE_GPIO EQU 1 ; Debug only since this is borrowed
TEST_GPIO_BIT EQU BIT24 ; Select the GPIO bit to use for tuning
LCD_DELAY_TIME EQU 0x1400000 ; 20 ms untuned (likely 60 or so).
TEXTAREA
LEAF_ENTRY OEMPowerOff
; OEMPowerOff - OFF button handler
;
; 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
mov pc, lr
LEAF_ENTRY OEMPowerOffIntel
;
; OEMPowerOff - OFF button handler
;
; 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
;
;
; Intel code
;
; In sleep mode the processor core is powered down. This means that
; we lose processor state (including banked registers), cache contents, etc.
; We count on WinCE to save the User Mode info but walk the other modes
; and save state.
;
; When we are called, the processor is in SVC mode with interrupts off
;
stmdb sp!, {r4-r12} ; Push SVC state onto our stack
stmdb sp!, {lr}
ldr r0, =GPIO_BASE_VIRTUAL
mvn r1, #0
str r1, [r0, #GPCR_OFFSET] ; turn off all GPIOs
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; base of Sleep mode storage
ldr r2, =Awake_address ; store Virtual return address
str r2, [r3], #4
;mrc p15, 0, r2, c1, c0 ; load r2 with MMU Control
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, [r3], #4 ; store MMU Control data
;mrc p15, 0, r2, c2, c0 ; load r2 with TTB address.
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, [r3], #4 ; store TTB address
mrc p15, 0, r2, c3, c0, 0 ; load r2 with domain access control.
str r2, [r3], #4 ; store domain access control
str sp, [r3], #4 ; store SVC stack pointer
mrs r2, spsr
str r2, [r3], #4 ; store 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} ; store 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} ; store 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} ; store 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} ; store 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} ; store the SYS mode Registers
mov r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Back to SVC mode, no interrupts
msr cpsr, r1
ldr r0, =GPIO_BASE_VIRTUAL ; Store GPIO registers
ldr r5, [r0, #GAFR_OFFSET]
str r5, [r3], #4
ldr r5, [r0, #GFER_OFFSET]
str r5, [r3], #4
ldr r5, [r0, #GRER_OFFSET]
str r5, [r3], #4
ldr r0, =OSC_BASE_VIRTUAL
ldmia r0!, {r4-r7} ; Get OSMR array
stmia r3!, {r4-r7}
ldmia r0!, {r4-r7} ; Get OSCR, OSSR, OWER, OIER
stmia r3!, {r4-r7}
ldr r0, =RTC_BASE_VIRTUAL
ldr r5, [r0, #RTTR_OFFSET]
str r5, [r3], #4
ldr r5, [r0, #RTSR_OFFSET]
str r5, [r3], #4
ldr r1, [r0, #RTSR_OFFSET]
orr r1, r1, #(RTC_AL|RTC_HZ) ; Clear Clock Interrupt Sources
str r1, [r0, #RTSR_OFFSET]
ldr r0, =IC_BASE_VIRTUAL
ldr r5, [r0, #ICMR_OFFSET]
str r5, [r3]
ldr r1, [r0, #ICMR_OFFSET]
and r1, r1, #GPIO_31
orr r1, r1, #(GPIO_0 | GPIO_1) ; Mask all interrupts but GPIO0 & GPIO1 (SW1)
str r1, [r0, #ICMR_OFFSET]
ldr r0, =PMC_BASE_VIRTUAL
orr r1, r1, #GPIO_23 ; DCD wakeup
;orr r1, r1, #GPIO_31 ; RTC ALARM wakeup
str r1, [r0, #PWER_OFFSET] ; Allow GPIO0/GPIO1,DCD,RTC
and r1, r1, #(~GPIO_0) ; DC - Disable rising
; edge interrupt for ON button.
ldr r0, =GPIO_BASE_VIRTUAL
str r1, [r0, #GRER_OFFSET] ; Enable Rising Edge source
; mov r1, #0
mov r1, #GPIO_0 ; DC - Support ON button falling edge to quick wakeup device
str r1, [r0, #GFER_OFFSET] ; Falling Edge source setting
mov r1, #GPIO_0:OR:GPIO_1 ; Clear any pending interrupts on SW1/2
str r1, [r0, #GEDR_OFFSET]
mov r1, #GPIO_23
str r1, [r0, #GEDR_OFFSET] ; clear any pending interrupts on DCD
; Is this debug trigger ??
; mov r1, #BIT17
; str r1, [r0, #GPSR]
; do Checksum on the Sleepdata
ldr r3, =SLEEPDATA_BASE_VIRTUAL ; get pointer to SLEEPDATA
mov r2, #0
ldr r0, =SLEEPDATA_SIZE ; get size of data structure (in words)
30
ldr r1, [r3], #4
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, =PMC_BASE_VIRTUAL
str r2, [r0, #PSPR_OFFSET] ; Store in Power Manager Scratch pad register
;------------------------------------------------------------------------
; At this point in the shutdown it is safe to use any registers
IF :DEF: TEST_TRACE_GPIO
ldr r0, =GPIO_BASE_VIRTUAL
mov r1, #TEST_GPIO_BIT
str r1, [r0, #GPCR_OFFSET] ; Clear the GPIO driver
ldr r1, [r0, #GPDR]
orr r1, r1, #TEST_GPIO_BIT
str r1, [r0, #GPDR_OFFSET] ; Enable GPIO bit as output (should go low)
ENDIF ; TEST_TRACE_GPIO
IF :DEF: TEST_EARLY_STOP_CBR
;------------------------------------------------------------------------
; Stop CBR refresh now, the SDRAM accesses below will be sufficient
mov r1, #MC_BASE_VIRTUAL ; memory controller base
ldr r0, [r1, #MDREFR_OFFSET] ; Get MDREFR
bic r0, r0, #0xff00 ; Clear DRI high
bic r0, r0, #0x00f0 ; and low part
str r0, [r1, #MDREFR_OFFSET] ; and save it
ENDIF ; TEST_EARLY_STOP_CBR
;------------------------------------------------------------------------
; Clean dcache. Use a reserved region for single length sweep. This needs
; to be very fast.
ldr r0, =ZBANK_BASE_C_VIRTUAL+CACHE_SIZE ; Address of C=1/B=1 zero space
ldr r1, =(CACHE_SIZE / CACHE_LINE) ; 8KB / 32Bytes/blk = 256 blk
40
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
subs r1, r1, #8
bne %b40
;------------------------------------------------------------------------
; Clean baby dcache. Use a reserved region as above.
ldr r0, =ZBANK_BASE_U_VIRTUAL+512 ; Address of C=1/B=0 zero space
mov r1, #16 ; .5KB / 32Bytes/blk = 16 blk
50
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
ldr r2, [r0], #CACHE_LINE
subs r1, r1, #8
bne %b50
mcr p15, 0, r0, c7, c10, 4 ; drain write buffer
;------------------------------------------------------------------------
; At this point all memory and register data is saved in SDRAM. Prepare
; for final shutdown.
ldr r0, =PMC_BASE_VIRTUAL
mov r1, #PCFR_OPDE ; Sleep mode function setup
str r1, [r0, #PCFR_OFFSET]
IF :DEF: TEST_DISABLE_INTERRUPT
;------------------------------------------------------------------------
; Disable all interrupts in case they have been left on. We can't get
; faulted out of this code. This should not be needed as interrupts are
; already disbled, but ...
ldr r1, =IC_BASE_VIRTUAL
mov r2, #0
str r2, [r1,#ICMR_OFFSET]
ENDIF ; TEST_DISABLE_INTERRUPT
IF :DEF: TEST_DISABLE_DMA
;------------------------------------------------------------------------
; Disable all DMA in case they have been left on. Any memory reference
; will cause the shutdown to fail.
ldr r1,=DMA_BASE_U_VIRTUAL
mov r2,#1
str r2,[r1, #0x08]
str r2,[r1, #0x28]
str r2,[r1, #0x48]
str r2,[r1, #0x68]
str r2,[r1, #0x88]
str r2,[r1, #0xA8]
ENDIF ; TEST_DISABLE_DMA
IF :DEF: TEST_DISABLE_LCD
;------------------------------------------------------------------------
; Disable the LCD controller. This *really* needs to be done in the
; power handler for the display driver.
IF :DEF: TEST_TRACE_GPIO
ldr r0, =GPIO_BASE_VIRTUAL
mov r1, #TEST_GPIO_BIT
str r1, [r0, #GPSR_OFFSET] ; Set to mark start (pin pulled high)
ENDIF ; TEST_TRACE_GPIO
;------------------------------------------------------------------------
; We need to stop the LCD as fast as possible. To do so we will drop the LPP
; to force the end of frame signal ASAP. We then disable the device and wait
; for LDD.
ldr r1,=LCD_BASE_VIRTUAL
;ldr r2,[r1,#LCCR2_OFFSET]
;bic r2,r2,#255 ; Clear LPP - not sure if this is legal,
; need to check
;bic r2,r2,#256 ; Clear LPP
mov r2,#0 ; Clear all counts
str r2,[r1,#LCCR2_OFFSET]
ldr r2,[r1,#LCCR0_OFFSET]
bic r2,r2,#1 ; Clear LEN
str r2,[r1,#LCCR0_OFFSET]
86 ldr r2,[r1,#LCSR_OFFSET]
tst r2,#1 ; Wait for LDD
bne %B86
IF :DEF: TEST_TRACE_GPIO
mov r1, #TEST_GPIO_BIT
str r1, [r0, #GPCR_OFFSET] ; And clear GPIO bit to mark end of window
ENDIF ; TEST_TRACE_GPIO
ENDIF ; TEST_DISABLE_LCD
IF :DEF: TEST_LCD_DELAY
;------------------------------------------------------------------------
; This method inserts a delay to allow the last frame to complete
; naturally. This will prevent any DMA activity during final shutdown
; but requires an additional 20ms in the shutdown path.
IF :DEF: TEST_TRACE_GPIO
ldr r0, =GPIO_BASE_VIRTUAL
mov r1, #TEST_GPIO_BIT
str r1, [r0, #GPSR_OFFSET] ; Set to mark start (pin pulled high)
ENDIF ; TEST_TRACE_GPIO
mov r1,#LCD_DELAY_TIME ; Give a bit of time to stop (20ms)
55 subs r1,r1,#1
bne %B55
IF :DEF: TEST_TRACE_GPIO
mov r1, #TEST_GPIO_BIT
str r1, [r0, #GPCR_OFFSET] ; And clear GPIO bit to mark end of window
ENDIF ; TEST_TRACE_GPIO
ENDIF ; TEST_LCD_DELAY
IF :DEF: TEST_SW_SHUTDOWN
;------------------------------------------------------------------------
; If we are using S/W shutdown go do it now
b SelfRefresh
ELSE
;------------------------------------------------------------------------
; If we are using H/W shutdown just hit the force sleep now and we're done
mov r1, #PMCR_SLEEPFORCE ; Force sleep entry
str r1, [r0, #PMCR_OFFSET]
58
b %B58 ; don't let it fall through
ENDIF ; TEST_SW_SHUTDOWN
;------------------------------------------------------------------------
; Software initiated shutdown sequence. We need to insure that memory activity
; is stopped and the system put to sleep.
;
; No registers need to be preserved since we will never come back.
;
ALIGN 32
SelfRefresh
; Set up all data in registers as we can not incur any memory cycles
; later in the shutdown.
mov r1, #MC_BASE_VIRTUAL ; memory controller base
ldr r4, [r1, #MSC0_OFFSET]
ldr r5, [r1, #MSC1_OFFSET]
ldr r6, [r1, #MSC2_OFFSET]
ldr r3, =0xfffcfffc ; use to clear RT fields of any VLIO
; also to clear DE bits in MDCNFG
and r4, r3, r4
and r5, r3, r5
and r6, r3, r6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -