diff options
-rw-r--r-- | arch/arm/mach-tegra/idle-t2.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-tegra/power-t2.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-tegra/power.h | 3 |
3 files changed, 31 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/idle-t2.c b/arch/arm/mach-tegra/idle-t2.c index 26c2bb7e3c8b..33625294df9f 100644 --- a/arch/arm/mach-tegra/idle-t2.c +++ b/arch/arm/mach-tegra/idle-t2.c @@ -57,6 +57,10 @@ extern struct wake_lock main_wake_lock; //Let Max LP2 time wait be 71 min (Almost a wrap around) #define LP2_MAX_WAIT_TIME_US (71*60*1000000ul) +#if NV_KBC_INTERRUPT_WORKAROUND +volatile void *g_pKBC; +#endif + // When non-zero, collects and prints aggregate statistics about idle times static volatile NvU8 *s_pFlowCtrl = NULL; @@ -222,6 +226,17 @@ void __init NvAp20InitFlowController(void) return; } +#if NV_KBC_INTERRUPT_WORKAROUND + NvRmModuleGetBaseAddress(s_hRmGlobal, + NVRM_MODULE_ID(NvRmModuleID_Kbc, 0), &pa, &len); + + if (NvRmPhysicalMemMap(pa, len, NVOS_MEM_READ_WRITE, + NvOsMemAttribute_Uncached, + (void**)&g_pKBC)!=NvSuccess) + { + return; + } +#endif s_pFlowCtrl = pTempFc; g_ArmPerif = (NvU32)pTempArmPerif; diff --git a/arch/arm/mach-tegra/power-t2.c b/arch/arm/mach-tegra/power-t2.c index 04e65a6795a6..e340298cc5ae 100644 --- a/arch/arm/mach-tegra/power-t2.c +++ b/arch/arm/mach-tegra/power-t2.c @@ -23,6 +23,7 @@ #include "power.h" #include "linux/interrupt.h" #include "nvassert.h" +#include "ap20/arapbdev_kbc.h" extern int enter_power_state(PowerState state, unsigned int proc_id); extern void prepare_for_wb0(void); @@ -43,6 +44,10 @@ void shadow_lp0_scratch_regs(void); extern NvRmDeviceHandle s_hRmGlobal; +#if NV_KBC_INTERRUPT_WORKAROUND +extern volatile void *g_pKBC; +#endif + uintptr_t g_resume = 0, g_contextSavePA = 0, g_contextSaveVA = 0; uintptr_t g_iramContextSaveVA = 0; NvU32 g_modifiedPlls; @@ -99,6 +104,13 @@ void cpu_ap20_do_lp0(void) prepare_for_wb0(); shadow_lp0_scratch_regs(); printk("LP0: Entering...\n"); + +#if NV_KBC_INTERRUPT_WORKAROUND + //Forcibly clear the interrupt. This will clear + //the KBC interrupt that is probably pending in the + //32KHz domain. + NV_WRITE32(g_pKBC + APBDEV_KBC_INT_0, 0x1); +#endif enter_power_state(POWER_STATE_LP0, 0); //Re-initialize the L2 cache @@ -721,7 +733,7 @@ unsigned int check_for_cpu1_reset(void) CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET_0); reg = reg & 0x2; - + return reg; } diff --git a/arch/arm/mach-tegra/power.h b/arch/arm/mach-tegra/power.h index 81a1130fa2da..ddca6fa3ce49 100644 --- a/arch/arm/mach-tegra/power.h +++ b/arch/arm/mach-tegra/power.h @@ -50,6 +50,9 @@ extern NvRmDeviceHandle s_hRmGlobal; #define WAKE_PAD_MIN_LATCH_TIME_US 130 #define WAKE_PAD_MIN_SAMPLE_TIME_US 70 +//Workaround for spurious KBC wake event +#define NV_KBC_INTERRUPT_WORKAROUND 1 + #define NV_CAR_REGR(pBase, reg)\ NV_READ32( (((NvUPtr)(pBase)) + CLK_RST_CONTROLLER_##reg##_0)) #define NV_CAR_REGW(pBase, reg, val)\ |