summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authortkasivajhula <tkasivajhula@nvidia.com>2010-04-02 16:55:28 -0700
committerGary King <gking@nvidia.com>2010-04-16 13:00:30 -0700
commitcd4556b05d4a09ed36cac8ba5258d81ffdab2f10 (patch)
tree74b37041e0ef79947737bd883045d724310a6096 /arch
parent0b29d48efb6302ebb74d551dccb2b7766c353f92 (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.h2
-rw-r--r--arch/arm/mach-tegra/idle-t2.c29
-rw-r--r--arch/arm/mach-tegra/init_common.c3
-rw-r--r--arch/arm/mach-tegra/power-lp.S92
-rw-r--r--arch/arm/mach-tegra/power-t2.c18
-rw-r--r--arch/arm/mm/cache-l2x0.c2
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;