diff options
author | tkasivajhula <tkasivajhula@nvidia.com> | 2010-04-02 16:55:28 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-04-16 13:00:30 -0700 |
commit | cd4556b05d4a09ed36cac8ba5258d81ffdab2f10 (patch) | |
tree | 74b37041e0ef79947737bd883045d724310a6096 /arch | |
parent | 0b29d48efb6302ebb74d551dccb2b7766c353f92 (diff) |
tegra power: Flush the L2 rams before entering LP0.
LP0 turns off core voltage. As a result, the L2 rams
need to be flushed prior to shutdown. The L2 cache
will be re-enabled after returning from LP0.
Change-Id: Ie6e69a3e5615393c5c6e7189b4d7e3559304e7f9
Reviewed-on: http://git-master/r/1036
Reviewed-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com>
Tested-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com>
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/hardware/cache-l2x0.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/idle-t2.c | 29 | ||||
-rw-r--r-- | arch/arm/mach-tegra/init_common.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/power-lp.S | 92 | ||||
-rw-r--r-- | arch/arm/mach-tegra/power-t2.c | 18 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 2 |
6 files changed, 131 insertions, 15 deletions
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 33d19e4160c4..0aea9c76712d 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -77,7 +77,7 @@ #define L2X0_EVENT_INTERRUPT_DISABLED 0x3 #ifndef __ASSEMBLY__ -extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); +extern void l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); extern bool l2x0_disabled; #endif diff --git a/arch/arm/mach-tegra/idle-t2.c b/arch/arm/mach-tegra/idle-t2.c index 14782d11ed8a..26c2bb7e3c8b 100644 --- a/arch/arm/mach-tegra/idle-t2.c +++ b/arch/arm/mach-tegra/idle-t2.c @@ -41,8 +41,9 @@ extern uintptr_t g_resume, g_contextSavePA, g_contextSaveVA; extern uintptr_t g_iramContextSaveVA; extern NvU32 g_NumActiveCPUs, g_ArmPerif; extern NvU32 g_enterLP2PA; -extern volatile void *g_pPMC, *g_pAHB, *g_pCLK_RST_CONTROLLER; +extern volatile void *g_pPMC, *g_pAHB, *g_pCLK_RST_CONTROLLER, *g_pRtc; extern volatile void *g_pEMC, *g_pMC, *g_pAPB_MISC, *g_pIRAM, *g_pTimerus; +extern volatile void *g_pPL310; #ifdef CONFIG_WAKELOCK extern struct wake_lock main_wake_lock; #endif @@ -192,7 +193,31 @@ void __init NvAp20InitFlowController(void) NvOsMemAttribute_Uncached, (void**)&g_pTimerus)!=NvSuccess) { - printk(KERN_INFO "failed to map iram; DVFS will not function" + printk(KERN_INFO "failed to map timerus; DVFS will not function" + " correctly as a result\n"); + return; + } + + NvRmModuleGetBaseAddress(s_hRmGlobal, + NVRM_MODULE_ID(NvRmModuleID_Rtc, 0), &pa, &len); + + if (NvRmPhysicalMemMap(pa, len, NVOS_MEM_READ_WRITE, + NvOsMemAttribute_Uncached, + (void**)&g_pRtc)!=NvSuccess) + { + printk(KERN_INFO "failed to map rtc; DVFS will not function" + " correctly as a result\n"); + return; + } + + NvRmModuleGetBaseAddress(s_hRmGlobal, + NVRM_MODULE_ID(NvRmPrivModuleID_Pl310, 0), &pa, &len); + + if (NvRmPhysicalMemMap(pa, len, NVOS_MEM_READ_WRITE, + NvOsMemAttribute_Uncached, + (void**)&g_pPL310)!=NvSuccess) + { + printk(KERN_INFO "failed to map pl310; DVFS will not function" " correctly as a result\n"); return; } diff --git a/arch/arm/mach-tegra/init_common.c b/arch/arm/mach-tegra/init_common.c index 3b149d206bd2..d5fae385502c 100644 --- a/arch/arm/mach-tegra/init_common.c +++ b/arch/arm/mach-tegra/init_common.c @@ -856,11 +856,12 @@ fail: #else #include <asm/hardware/cache-l2x0.h> #include "ap20/arpl310.h" -static void __init tegra_pl310_init(void) +void tegra_pl310_init(void) { NvRmPhysAddr CachePa; NvU32 Len; volatile NvU8 *pCache = NULL; + NvU32 AuxValue = NV_DRF_NUM(PL310, AUXILIARY_CONTROL, FULL_LINE_OF_ZERO, 1) | NV_DRF_NUM(PL310, AUXILIARY_CONTROL, SO_DEV_HIGH_PRIORITY, 0) | diff --git a/arch/arm/mach-tegra/power-lp.S b/arch/arm/mach-tegra/power-lp.S index f7e65d74b74d..2b693afc4186 100644 --- a/arch/arm/mach-tegra/power-lp.S +++ b/arch/arm/mach-tegra/power-lp.S @@ -29,6 +29,7 @@ #include "ap20/arapbpm.h" #include "ap20/aremc.h" #include "ap20/arapb_misc.h" +#include "ap20/arpl310.h" #include "nvrm_drf.h" #if defined(CONFIG_ARCH_TEGRA_2x_SOC) @@ -47,7 +48,7 @@ #define CSITE_CPUDBG0_LAR_0 0x10fb0 #define CSITE_CPUDBG1_LAR_0 0x12fb0 #define TEMP_AREA_SIZE 32 -#define DEBUG_FORCE_RTC_WAKEUP 5 +#define DEBUG_FORCE_RTC_WAKEUP_SEC 0 #else #error "Unrecognized Tegra SoC Family" #endif @@ -122,7 +123,7 @@ ArmCortexA9Saved: ldr r5, =enter_lp0_end ldr r6, =enter_lp0 - //For LP0, the AVP stores it's continuation address at the first + //For LP0, the AVP stores its 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. @@ -136,6 +137,65 @@ ArmCortexA9Saved: //Store in scratch39 str r1, [r3, #APBDEV_PMC_SCRATCH39_0] + //Flush L2 rams for LP0 + ldr r1, =g_pPL310 + ldr r1, [r1] + + ldr r2, [r1, #PL310_CONTROL_0] + ands r2, r2, #0x1 + beq copy_to_iram + + //Clear L2 restoration ptr + ldr r3, =g_contextSaveVA + ldr r3, [r3] + + mov r2, #0 + str r2, [r3, #0x30] + + dsb + + //Lock all ways + add r10, r1, #PL310_DATA_LOCKDOWN0_0 + //16 lockdown registers => 64 bytes register space + add r2, r10, #64 + //r3 = 0xff = ALL_WAYS + mov r3, #0xff + +lock_all_ways: + str r3, [r10] + add r10, r10, #4 + + cmp r10, r2 + bne lock_all_ways + + //Clean all ways + mov r2, #0xff + str r2, [r1, #PL310_CLEAN_BY_WAY_0] + +wait_for_l2_flush: + ldr r2, [r1, #PL310_CLEAN_BY_WAY_0] + cmp r2, #0 + bne wait_for_l2_flush + + //Issue a cache sync + mov r2, #0 + str r2, [r1, #PL310_CACHE_SYNC_0] + dsb + + //Unlock all ways + add r10, r1, #PL310_DATA_LOCKDOWN0_0 + //16 lockdown registers => 64 bytes register space + add r2, r10, #64 + //r3 = 0 = BITMAP_NO_WAYS + mov r3, #0 + +unlock_all_ways: + str r3, [r10] + add r10, r10, #4 + + cmp r10, r2 + bne unlock_all_ways + 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. @@ -462,7 +522,7 @@ pad_susp_end: bic r2, r2, #(1<<14) str r2, [r5, #APBDEV_PMC_CNTRL_0] - //Switch CPU clocks to CLKM + //Switch CPU clocks to CLKM mov r2, #0 orr r2, r2, #(1<<28) str r2, [r8, #CLK_RST_CONTROLLER_CCLK_BURST_POLICY_0] @@ -754,13 +814,14 @@ is_self: orr r2, r2, #1 str r2, [r6, #FLOW_CTLR_CPU_CSR_0] +#if DEBUG_FORCE_RTC_WAKEUP_SEC //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 + add r2, r2, #DEBUG_FORCE_RTC_WAKEUP_SEC rtc_idle1: ldr r1, [r0, #0x4] tst r1, #0x1 @@ -777,6 +838,7 @@ rtc_idle3: ldr r1, [r0, #0x4] tst r1, #0x1 bne rtc_idle3 +#endif //Save the microsecond count before LP0 in SCRATCH38 ldr r2, [r7] str r2, [r5, #APBDEV_PMC_SCRATCH38_0] @@ -855,6 +917,28 @@ pll_wait: ldr r1, =0x20008888 str r1, [r0, #0x20] +#if DEBUG_FORCE_RTC_WAKEUP_SEC + //Clear the pending rtc interrupt + ldr r0, =g_pRtc + ldr r0, [r0] +rtc_idle4: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle4 + mov r2, #0 + str r2, [r0, #0x28] +rtc_idle5: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle5 + //clear interrupt + mov r2, #1 + str r2, [r0, #0x2c] +rtc_idle6: + ldr r1, [r0, #0x4] + tst r1, #0x1 + bne rtc_idle6 +#endif skip_pll: //Restore the cpu virtual context b ArmCortexA9VirtualRestore diff --git a/arch/arm/mach-tegra/power-t2.c b/arch/arm/mach-tegra/power-t2.c index 1916e1663a65..04e65a6795a6 100644 --- a/arch/arm/mach-tegra/power-t2.c +++ b/arch/arm/mach-tegra/power-t2.c @@ -22,11 +22,13 @@ #include "power.h" #include "linux/interrupt.h" +#include "nvassert.h" extern int enter_power_state(PowerState state, unsigned int proc_id); extern void prepare_for_wb0(void); extern void prepare_for_wb1(void); extern NvU32* perform_context_operation(PowerModuleContext Context); +extern void tegra_pl310_init(void); void cpu_ap20_do_lp2(void); void resume(unsigned int state); @@ -39,7 +41,6 @@ static void init_lp0_scratch_registers(void); void shadow_runstate_scratch_regs(void); void shadow_lp0_scratch_regs(void); - extern NvRmDeviceHandle s_hRmGlobal; uintptr_t g_resume = 0, g_contextSavePA = 0, g_contextSaveVA = 0; @@ -52,7 +53,7 @@ NvU32 g_coreSightClock, g_currentCcbp; NvU32 g_lp1CpuPwrGoodCnt, g_currentCpuPwrGoodCnt; volatile void *g_pPMC, *g_pAHB, *g_pCLK_RST_CONTROLLER; volatile void *g_pEMC, *g_pMC, *g_pAPB_MISC, *g_pTimerus; -volatile void *g_pIRAM; +volatile void *g_pIRAM, *g_pRtc, *g_pPL310; #define WAKEUP_SOURCE_INT_RTC 16 #define INVALID_IRQ (0xFFFF) @@ -71,9 +72,6 @@ void cpu_ap20_do_lp0(void) NvOdmPmuProperty PmuProperty; NvBool HasPmuProperty = NvOdmQueryGetPmuProperty(&PmuProperty); - //Inform RM about entry to LP0 state - NvRmPrivPowerSetState(s_hRmGlobal, NvRmPowerState_LP0); - if (HasPmuProperty && PmuProperty.CombinedPowerReq) { //Enable core power request, and tristate CPU power request outputs @@ -89,6 +87,8 @@ void cpu_ap20_do_lp0(void) APBDEV_PMC_CNTRL_0); Reg = NV_FLD_SET_DRF_DEF(APBDEV_PMC, CNTRL, CPUPWRREQ_OE, DISABLE, Reg); + NV_REGW(s_hRmGlobal, NvRmModuleID_Pmif, 0, + APBDEV_PMC_CNTRL_0, Reg); } //Store the scratch1 value first. This scratch is clobbered @@ -100,6 +100,12 @@ void cpu_ap20_do_lp0(void) shadow_lp0_scratch_regs(); printk("LP0: Entering...\n"); enter_power_state(POWER_STATE_LP0, 0); + + //Re-initialize the L2 cache + tegra_pl310_init(); + + //Inform RM about entry to LP0 state + NvRmPrivPowerSetState(s_hRmGlobal, NvRmPowerState_LP0); printk("LP0: Exited...\n"); shadow_runstate_scratch_regs(); @@ -261,7 +267,7 @@ void power_lp0_init(void) //Enable CPU power request. Leave it enabled to be ready for LP2/LP1. Reg = NV_PMC_REGR(g_pPMC, CNTRL); Reg = NV_FLD_SET_DRF_DEF(APBDEV_PMC, CNTRL, CPUPWRREQ_OE, ENABLE, Reg); - NV_PMC_REGW(g_pPMC, CNTRL, Reg); + NV_ASSERT(Reg == APBDEV_PMC_CNTRL_0_CPUPWRREQ_OE_ENABLE); //If the system supports deep sleep (LP0), initialize PMC accordingly. if (LPStateInfo->LowestPowerState == NvOdmSocPowerState_DeepSleep) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index ca8d1038afd4..1daa4d09e8f3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -159,7 +159,7 @@ void l2x0_deinit(void) spin_unlock_irqrestore(&l2x0_lock, flags); } -void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) +void l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) { __u32 aux; |