📄 fw_utils.s_sleep
字号:
;/* Ensure that MPMC is idle */
LDR r1,=( MPMCStatus_B_Busy )
wait
LDR r2,[r0,#MPMCStatus] ;/* read MPMC status register */
AND r2,r2,r1 ;/* mask */
CMP r2,r1 ;/* keep polling until MPMC is idle */
BNE wait ;/* branch if result of AND is not zero */
;/*
; * Now the MPMC can be disabled
; * The MPMC is no longer busy which informs us the buffers are flushed,
; * we can now carry on with initialization
; */
LDR r1, =( MPMCControl_L_NormalPower :OR: MPMCControl_E_Disable )
STR r1, [r0,#MPMCControl] ;/* r1=0x0 */
;/* Wait 100ms to ensure clocks have stabilised */
LDR r0, =100000
MOV r1, #0
BL uSecsWait
LDR r0, =PHYS_MPMC_CNTL_BASE
;/*
; * Configure SDRAM init to NOP in MPMCDynamicControl register
; * Clock enable signal should be high during SDRAM initialisation
; */
LDR r1, =(MPMCDynamicControl_MPMCRPVHHOUT_Normal:OR:MPMCDynamicControl_nRP_Low:OR:MPMCDynamicControl_DP_PowerNormal:OR:MPMCDynamicControl_I_SDRAMNOP:OR:MPMCDynamicControl_SR_Normal :OR: MPMCDynamicControl_CS_Continuous :OR: MPMCDynamicControl_CE_Enable)
STR r1, [r0,#MPMCDynamicControl] ;/* r1=0x183 */
;/* Wait 200ms */
LDR r0, =200000
MOV r1, #0
BL uSecsWait
LDR r0, =PHYS_MPMC_CNTL_BASE
;/* Set SDRAM init to PALL to precharge all banks */
LDR r1, =(MPMCDynamicControl_MPMCRPVHHOUT_Normal :OR: MPMCDynamicControl_nRP_Low :OR: MPMCDynamicControl_DP_PowerNormal :OR: MPMCDynamicControl_I_SDRAMPALL :OR: MPMCDynamicControl_SR_Normal :OR: MPMCDynamicControl_CS_Continuous :OR: MPMCDynamicControl_CE_Enable)
STR r1, [r0, #MPMCDynamicControl] ;/* r1=0x103 */
;/* Perform some refresh cycles by writing 1 into the refresh register,
; * this provides a refresh every 16 AHB cycles
; */
MOV r1, #1
STR r1, [r0, #MPMCDynamicRefresh]
;/*
; * Wait 128 AHB cycles
; * NOTE: Here we just wait for 1ms
; */
LDR r0, =1000
MOV r1, #0
BL uSecsWait
LDR r0, =PHYS_MPMC_CNTL_BASE
;/*
; * Program operational refresh register values
; *
; * To program the operational value in the refresh register, this example
; * assumes a requirement of memory refresh every 15.625us and a 100MHz
; * HCLK. The refresh register must be programmed with
; * (15.625us * 100MHz)/16 = 98 = 0x62
; */
MOV r1, #0x62
STR r1, [r0, #MPMCDynamicRefresh]
;/* Set up memory Bank 0 */
;/* Program operational latency register values, for this example CAS and
; * RAS are set to 2
; */
LDR r1, =(MPMCDynamicRasCas_CAS_2_0_Cycles:OR:MPMCDynamicRasCas_RAS_2Cycles)
STR r1, [r0, #MPMCDynamicRasCas0] ;/* r1=0x202 */
;/*
; * Program operational values in MPMCDynamicConfig[0], buffers must be
; * disabled during initialisation
; * Memory being configured is 64Mb of 32bit SDRAM (4MX16)
; */
LDR r1, =(MPMCDynamicConfig_P_WriteNotProtect:OR:MPMCDynamicConfig_AM_32bit_4Mx16:OR:MPMCDynamicConfig_MD_SDR)
STR r1, [r0, #MPMCDynamicConfig0] ;/* r1=<-> */
;/* The other memory Banks could be setup at this point if required */
;/* Set SDRAM init to MODE in MPMCDynamicControl */
LDR r1, =(MPMCDynamicControl_MPMCRPVHHOUT_Normal :OR: MPMCDynamicControl_nRP_Low :OR: MPMCDynamicControl_DP_PowerNormal :OR: MPMCDynamicControl_I_SDRAMMODE :OR: MPMCDynamicControl_SR_Normal :OR: MPMCDynamicControl_CS_Continuous :OR: MPMCDynamicControl_CE_Enable)
STR r1, [r0, #MPMCDynamicControl] ;/* r1=0x83 */
;/* Program memory's mode register for burst length, burst type, CAS
; * latency, operating mode, write burst mode
; */
LDR r1, =PHYS_RAM_BASE
ADD r1, r1, #0x20000 ;/* this magic number is taken from the Micron MT48LC4M16A2 SDRAM example in the PL175 TRM */
LDR r1, [r1, #0x0]
;/* Set SDRAM initialization value to NORMAL in MPMCDynamicControl */
LDR r1, =(MPMCDynamicControl_MPMCRPVHHOUT_Normal :OR: MPMCDynamicControl_nRP_Low :OR: MPMCDynamicControl_DP_PowerNormal :OR: MPMCDynamicControl_I_SDRAMNORMAL :OR: MPMCDynamicControl_SR_Normal :OR: MPMCDynamicControl_CS_Continuous :OR: MPMCDynamicControl_CE_Enable)
STR r1, [r0, #MPMCDynamicControl] ;/* r1=0x3 */
;/* Enable buffers in MPMCDynamicConfig */
LDR r1, =(MPMCDynamicConfig_P_WriteNotProtect :OR: MPMCDynamicConfig_AM_32bit_4Mx16 :OR: MPMCDynamicConfig_MD_SDR)
STR r1, [r0, #MPMCDynamicConfig0] ;/* r1=<-> */
;/*
; * Memory clock is disabled and clock control is set to low
; * This ensures that the MPMCCLKOUT will stop when SDRAMs are idle &
; * in self-refresh mode
; * The clock enable of idle devices is deasserted to save power
; */
LDR r1, =(MPMCDynamicControl_MPMCRPVHHOUT_Normal :OR: MPMCDynamicControl_nRP_Low :OR: MPMCDynamicControl_DP_PowerNormal :OR: MPMCDynamicControl_I_SDRAMNORMAL :OR: MPMCDynamicControl_SR_Normal :OR: MPMCDynamicControl_CS_Stop :OR: MPMCDynamicControl_CE_Disable)
STR r1, [r0, #MPMCDynamicControl] ;/* r1=0x0 */
;/* Enable the MPMC */
LDR r1, =( MPMCControl_L_NormalPower :OR: MPMCControl_E_Enable )
STR r1, [r0,#MPMCControl] ;/* r1=0x01 */
MOV pc,lr
ENTRY_END MPMCConfigMemory
; ****************************************************************************
; * SSMCConfigMemory
; *
; * Configures the parameters for the Synchronous Static Memory Controller,
; * Memory Bank 7
; *
; ****************************************************************************
LEAF_ENTRY SSMCConfigMemory
LDR r0, =PHYS_SSMC_CNTL_BASE ;/* load the SSMC physical base address */
MOV r1, #0
STR r1, [r0, #SMB093IDCYR7] ;/* Idle-cycle control register, no turn-around cycle delay */
MOV r1, #0 ;/* set for 0 wait states */
STR r1, [r0, #SMB093WStRdR7] ;/* Wait State 1 Control Register */
MOV r1, #0
STR r1, [r0, #SMB093WSTOENR7] ;/* Output enable assertion delay, no delay */
MOV r1, #0
STR r1, [r0, #SMB093WSTWENR7] ;/* write enable assertion delay, no delay */
;/* This is not really required as we are configuring for ROM */
;/*
; * Configure the control register for Memory Bank 7
; * The values are set to RBLE deasserted high, wait polarity low, external wait signal disabled,
; * chip select polarity low,write protection enabled, burst mode disabled, memory bus width 32-bits
; */
LDR r1,=SMB093CR_RBLE_Low ;r1 = 1
LDR r2,=SMB093CR_WaitPol_Low ;r2 = 0
ORR r1,r1,r2
LDR r2,=SMB093CR_WaitEn_Low ;r2 = 0
ORR r1,r1,r2
LDR r2,=SMB093CR_WP_Enabled ; r2 = 0x08 zq add 040803 /*r2 = 0x10*/
ORR r1,r1,r2
LDR r2,=SMB093CR_BmRd_Dis ;r2 = 0
ORR r1,r1,r2
LDR r2,=SMB093CR_BmWr_Dis ;r2 = 0
ORR r1,r1,r2
LDR r2,=SMB093CR_MW_32BIT ;r2 = 0x20 zq add 040803 /*r2 = 0x80*/
ORR r1,r1,r2 ;r1 = 0x29 zq add 040803 /*r1 = 0x91*/
STR r1, [r0, #SMB093CR7]
;/*
; * Check if the status register has any errors
; * This code just loops infinitely if any error is detected
; */
LDR r1, [r0, #SMB093SR7]
LDR r2, =SMB093SR_ErrorFlags
ANDS r1, r1, r2
;ZQ Modified 040804 ,
; BNE InfiniteLoop
BEQ InfiniteLoop
MOV pc, lr
InfiniteLoop
B InfiniteLoop
ENTRY_END SSMCConfigMemory
; ****************************************************************************
; * RemapSSMC
; *
; * Upon power reset, the bootcode is run from address 0x0, due to address
; * remapping functionality. This aliases the SSMC memory bank 7 to address 0x0
; * and the bootloader image is run from this address. As the hardware does not
; * support remapping we must manually return the PC back to the base address
; * of bank 7 ie PHYS_FLASH_BASE and execute the boot image from there.
; *
; * RemapSSMC calculates the correct offset to run enable the image to run
; * from memory bank 7 of SSMC
; *
; ****************************************************************************
LEAF_ENTRY RemapSSMC
MOV r2, lr
MOV r1, #PHYS_FLASH_BASE ;base address of the SSMC memory bank 7
ADD r2, r2, r1 ;get the correct offset
MOV pc, r2 ;go to the correct instruction within SSMC bank 7
NOP ;account for pipelining
NOP
ENTRY_END RemapSSMC
; ****************************************************************************
; * RemapRAM
; *
; * When the Remap functionality is switched off, memory from address 0x0 is
; * available as RAM. RemapRAM calculates the correct offset to enable the
; * image to execute from RAM
; *
; ****************************************************************************
LEAF_ENTRY RemapRAM
MOV r2, lr
SUB r2, r2, #PHYS_FLASH_BASE ;get the correct offset
MOV r1, #0x0 ;RAM starts at address 0x0
ADD r2, r2, r1 ;add the offset to the RAM base address
MOV pc, r2 ;go to the correct instruction in RAM
ENTRY_END RemapRAM
ENDIF ; EXAMPLE_MEMCONFIG
IF :DEF: EXAMPLE_POWERDOWN
; **** NOTE: ****
; The following is example code for powering down and putting RAM into refresh
; mode and has not been fully tested and is for reference only.
; You will need to alter and test the following code on your system.
; ***************
; Retry counter
COUNTER EQU 0x8000
; Example settings here are a 100MHz HCLK and 1MHz timer.
; Therefore 66000 HCLK cycles equate to:
HCLK_66000 EQU 660
IF EBOOT
ELSE
; ****************************************************************************
;
; ARM_PowerOff
;
; 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-r4
; r0 - general purpose
; r1 - general purpose
; r2 - general purpose
; r3 - VIC IntEnable contents
; r4/r5 - peripheral clocks that were enabled before going to sleep
;
; ****************************************************************************
LEAF_ENTRY ARM_PowerOff
; Disable IRQ and FIQ
mrs r0, cpsr
mrc p15, 0, r1, c13, c0, 0 ; Read the PID value into r1
stmfd sp!, {r0,r1,r4,r5,lr} ; Save current value of CPSR & LR & PID on stack
; Write 0 PID value into CP15 to enable "standard" MMU map
; otherwise we can enter with the Fast Context Switch extensions
; that will be remapping what appears to be the bottom of memory - even with
; the MMU turned off.
mov r1, #0
mcr p15, 0, r1, c13, c0, 0
orr r0, r0, #0xC0 ; Set FIQ and IRQ disable bits
msr cpsr, r0 ; Disable FIQ and IRQ
; Switch off all unused peripheral clocks.
; Leave HCLKSMC, HCLKSDRAM & MPMCCLK & PCLKUART2(UARTDEBUG) enabled.
; Load the System Controller virtual base address
; ldr r0, =VA_SC_BASE
; ldr r4, [r0, #ARM_CLKGATED1] ; Store the currently enabled peripheral clocks for reenbling upon wakeup
; ldr r2, =(:NOT:SCPerClkEnPhase1)
; str r2, [r0, #ARM_SCPerDis] ;
ldr r0, =VA_SC_BASE
ldr r4, [r0, #ARM_CLKGATED1] ; Store the currently enabled peripheral clocks for reenbling upon wakeup
ldr r5, [r0, #ARM_CLKGATED2] ; Store the currently enabled peripheral clocks for reenbling upon wakeup
ldr r2, =SCPerClkEnPhase1
str r2, [r0, #ARM_CLKGATED1]
ldr r2, =SCPerClkPclkUart2
str r2, [r0, #ARM_CLKGATED2]
; Get physical address for branch
ldr r0, =ReenableICache ; Jump to a label
IF :DEF: EXEFLASH
sub r0, r0, #(0x80000000 - PHYS_FLASH_BASE) ; Change from VA to PA
ELSE
sub r0, r0, #(0x88000000 - PHYS_RAM_BASE ) ; Change from VA to PA
ENDIF
mov r3, r0 ; Save physical address in R3
ldr lr, =EnableCaches ; Save virtual address in LR
; Disable D Cache
mrc p15, 0, r1, c1, c0, 0 ; Read control register
bic r1, r1, #0x0004 ; Clear the Enable D Cache bit
mcr p15, 0, r1, c1, c0, 0 ; Disable D cache
bic r1, r1, #0x0001 ; Clear the Enable MMU bit
bic r1, r1, #0x1000 ; Clear the Enable I Cache bit
; Detect the chip running
mrc p15, 0, r0, c0, c0, 0
mov r0, r0, LSL #16
mov r0, r0, LSR #20 ; R0 = 0x920 or 0x926
cmp r0, #0x920
bne TestCleanInvalidate
; Clean the entire DCache for ARM920
mov r0, #0 ; R0 = index [31:26]; seg [7:5]
NextLoop
mcr p15, 0, r0, c7, c14, 2 ; Clean & Invalidate DCache single entry (using index)
adds r0, r0, #0x4000000 ; index++
bcc NextLoop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -