diff options
Diffstat (limited to 'arch/arm/mach-tegra/power-lp.S')
-rw-r--r-- | arch/arm/mach-tegra/power-lp.S | 115 |
1 files changed, 104 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/power-lp.S b/arch/arm/mach-tegra/power-lp.S index acc7645e34c1..ad21c95aee25 100644 --- a/arch/arm/mach-tegra/power-lp.S +++ b/arch/arm/mach-tegra/power-lp.S @@ -41,6 +41,7 @@ #define CSITE_CPUDBG0_LAR_0 0x10fb0 #define CSITE_CPUDBG1_LAR_0 0x12fb0 #define TEMP_AREA_SIZE 16 +#define DEBUG_FORCE_RTC_WAKEUP 5 #else #error "Unrecognized Tegra SoC Family" #endif @@ -52,6 +53,7 @@ ENTRY(enter_power_state) //with IRQs turned off mrs r2, CPSR stmfd sp!, {r0-r12, lr} + stmfd sp!, {r0} cmp r1, #0 bne save_arm_state @@ -92,10 +94,73 @@ ArmCortexA9Saved: ands r2, r2, #0x3 bne reset_slave + //Check which power state we want to enter + ldmfd sp!, {r0} + //Is it LP2? + cmp r0, #0 + ldreq r2, =g_enterLP2PA + ldreq r2, [r2] + beq transition_to_state + + ldr r4, =g_pIRAM + ldr r4, [r4] + + //Is it LP1? + cmp r0, #1 + ldreq r2, =g_enterLP2PA + ldreq r2, [r2] + + //Is it LP0? + cmp r0, #2 + ldr r5, =enter_lp0_end + ldr r6, =enter_lp0 + + //For LP0, the AVP stores it's continuation address at the first + //location in IRAM. Before we overwrite IRAM with the LP0 entry + //code, copy the AVP continuation and store it in the scratch + //register dedicated for this purposed. + + //R1 = *g_pIRAM + ldr r1, [r4] + //R3 = &(g_pPMC) + ldr r3, =g_pPMC + //R3 = g_pPMC + ldr r3, [r3] + //Store in scratch39 + str r1, [r3, #APBDEV_PMC_SCRATCH39_0] + +copy_to_iram: + //Copy the enter_lp0 function to IRAM using 8x4 block moves. + //It doesn't matter if we copy a few extra words. + //IRAM has already been safely saved by the AVP at this point + //R4 = destination address to copy code to + //R5 = size of code to copy in bytes + //R6 = source address to copy code from + + //r2 is the source address + cpy r2, r6 + //r3 is the size to copy + sub r3, r5, r6 + +copy_code: + //Load source + ldmia r2!, {r5-r12} + //Store at destination + stmia r4!, {r5-r12} + //Decrement count + subs r3, r3, #32 + bgt copy_code + + //Get the physical address of IRAM + //This is where we will jump to start LP0 + ldr r2, =g_IramPA + ldr r2, [r2] + //We are the master. We should //turn of MMUs and caches. //Write a value to unblock the slaves +transition_to_state: //Turn off caches and MMU mrc p15, 0, r3, c1, c0, 0 bic r3, r3, #(1<<12) //I-Cache @@ -108,9 +173,6 @@ ArmCortexA9Saved: ldr r1, =g_wakeupCcbp ldr r1, [r1] - ldr r2, =g_enterLP2PA - ldr r2, [r2] - mov r10, #0 mcr p15, 0, r10, c8, c7, 0 // invalidate TLB dsb @@ -119,7 +181,7 @@ ArmCortexA9Saved: //Disable L1 caches and MMU mcr p15, 0, r3, c1, c0, 0 - //Finish up LP2 by entering flow control state + //Jump to the appropriate LPx function //bl enter_lp2 bx r2 @@ -148,6 +210,7 @@ wait_for_master: str r3, [r2] finish_power_state: + ldmfd sp!, {r0} ldmfd sp!, {r0-r12, lr} bx lr ENDPROC(EnterPowerState) @@ -343,10 +406,11 @@ TempStoreArea: ENDPROC(exit_lp2) ENTRY(enter_lp0) - ldr r4, [pc, #0x84] //EMC base - ldr r5, [pc, #0x84] //PMC base - ldr r6, [pc, #0x84] //FLOW base - ldr r7, [pc, #0x84] //TIMERUS base + ldr r4, [pc, #0xC8] //EMC base + ldr r5, [pc, #0xC8] //PMC base + ldr r6, [pc, #0xC8] //FLOW base + ldr r7, [pc, #0xC8] //TIMERUS base + ldr r8, [pc, #0xC8] //RTC base //Flush the write buffer dmb @@ -388,6 +452,29 @@ is_self: orr r2, r2, #1 str r2, [r6, #8] + //r0 = RTC_BASE + mov r0, r8 + //setup rtc wake + ldr r2, [r0, #0x10] //milli + ldr r2, [r0, #0x8] //shadow + + add r2, r2, #DEBUG_FORCE_RTC_WAKEUP +rtc_idle1: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle1 + str r2, [r0, #0x14] +rtc_idle2: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle2 + //intr mask alarm0 + mov r2, #1 + str r2, [r0, #0x28] +rtc_idle3: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle3 //Save the microsecond count before LP0 ldr r2, [r7] str r2, [r5, #0x134] @@ -403,6 +490,8 @@ do_wfi: andvc lr, r0, r0, lsl #8 andvs r7, r0, r0 andvs r5, r0, r0, lsl r0 + .word 0x7000e000 +enter_lp0_end: ENDPROC(enter_lp0) ENTRY(exit_power_state) @@ -443,8 +532,10 @@ ArmCortexA9PhysicalRestored: //Check if power state is POWER_STATE_LP0 cmp r0, #2 bne skip_pll - ldr r0, =PMC_PA_BASE - ldr r1, =TIMERUS_PA_BASE + ldr r0, =g_pPMC + ldr r0, [r0] + ldr r1, =g_pTimerus + ldr r1, [r1] //Read from LP0 exit time from SCRATCH1 ldr r2, [r0, #0x54] @@ -455,7 +546,8 @@ pll_wait: blt pll_wait //Put CPU clock source on PLLX - ldr r0, =CLK_RST_PA_BASE + ldr r0, =g_pCLK_RST_CONTROLLER + ldr r0, [r0] ldr r1, =0x20008888 str r1, [r0, #0x20] @@ -482,6 +574,7 @@ ArmCortexA9VirtualRestored: skip_local_timer_restore: //Restore the stack registers + ldmfd sp!, {r0} ldmfd sp!, {r0-r12, lr} //Restore the CPSR stored in r2 |