summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/idle-t2.c15
-rw-r--r--arch/arm/mach-tegra/power-t2.c14
-rw-r--r--arch/arm/mach-tegra/power.h3
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)\