summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/odm_kit/query/whistler/nvodm_query.c4
-rw-r--r--arch/arm/mach-tegra/suspend-t2.c23
-rw-r--r--arch/arm/mach-tegra/suspend.c37
-rw-r--r--arch/arm/mach-tegra/tegra2_save.S30
4 files changed, 86 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/odm_kit/query/whistler/nvodm_query.c b/arch/arm/mach-tegra/odm_kit/query/whistler/nvodm_query.c
index fab62d92bfcd..841798ed9d73 100644
--- a/arch/arm/mach-tegra/odm_kit/query/whistler/nvodm_query.c
+++ b/arch/arm/mach-tegra/odm_kit/query/whistler/nvodm_query.c
@@ -581,8 +581,8 @@ static NvOdmWakeupPadInfo s_NvOdmWakeupPadInfo[] =
{NV_FALSE, 13, NvOdmWakeupPadPolarity_Low}, // Wake Event 13 - sdio1_dat1
{NV_FALSE, 14, NvOdmWakeupPadPolarity_AnyEdge}, // Wake Event 14 - gp3_pv[6] (WLAN_INT)
{NV_FALSE, 15, NvOdmWakeupPadPolarity_AnyEdge}, // Wake Event 15 - gmi_ad16 (SPI3_DOUT, DTV_SPI4_CS1)
- {NV_FALSE, 16, NvOdmWakeupPadPolarity_High}, // Wake Event 16 - rtc_irq
- {NV_TRUE, 17, NvOdmWakeupPadPolarity_High}, // Wake Event 17 - kbc_interrupt
+ {NV_TRUE, 16, NvOdmWakeupPadPolarity_High}, // Wake Event 16 - rtc_irq
+ {NV_FALSE, 17, NvOdmWakeupPadPolarity_High}, // Wake Event 17 - kbc_interrupt
{NV_FALSE, 18, NvOdmWakeupPadPolarity_Low}, // Wake Event 18 - pwr_int (PMIC_INT)
{NV_FALSE, 19, NvOdmWakeupPadPolarity_AnyEdge}, // Wake Event 19 - usb_vbus_wakeup[0]
{NV_FALSE, 20, NvOdmWakeupPadPolarity_High}, // Wake Event 20 - usb_vbus_wakeup[1]
diff --git a/arch/arm/mach-tegra/suspend-t2.c b/arch/arm/mach-tegra/suspend-t2.c
index ed1055687baf..1cff68f878e9 100644
--- a/arch/arm/mach-tegra/suspend-t2.c
+++ b/arch/arm/mach-tegra/suspend-t2.c
@@ -24,6 +24,8 @@
#include <linux/init.h>
#include <asm/io.h>
#include <mach/iomap.h>
+#include "nvbootargs.h"
+#include <nvrm_memmgr.h>
#define PMC_SCRATCH3 0x5c
#define PMC_SCRATCH5 0x64
@@ -49,6 +51,7 @@
#define PMC_SCRATCH35 0x128
#define PMC_SCRATCH36 0x12c
#define PMC_SCRATCH40 0x13c
+#define PMC_SCRATCH41 0x140
struct pmc_scratch_field {
void __iomem *addr;
@@ -328,9 +331,16 @@ static const struct pmc_scratch_reg scratch[] __initdata = {
scratch(PMC_SCRATCH40, xm2_cfgd),
};
+extern void tegra_lp2_startup(void);
+extern NvRmDeviceHandle s_hRmGlobal;
+unsigned int s_AvpWarmbootEntry;
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+
void __init lp0_suspend_init(void)
{
int i;
+ NvBootArgsWarmboot WarmbootArgs;
+ NvRmMemHandle s_hWarmboot = NULL;
for (i=0; i<ARRAY_SIZE(scratch); i++) {
unsigned int r = 0;
@@ -346,4 +356,17 @@ void __init lp0_suspend_init(void)
writel(r, scratch[i].scratch_addr);
}
+
+ NvOsBootArgGet(NvBootArgKey_WarmBoot,
+ &WarmbootArgs, sizeof(NvBootArgsWarmboot));
+ if (NvRmMemHandleClaimPreservedHandle(s_hRmGlobal,
+ WarmbootArgs.MemHandleKey, &s_hWarmboot)) {
+ printk("Could not locate Warm booloader!\n");
+ }
+ else {
+ s_AvpWarmbootEntry = NvRmMemPin(s_hWarmboot);
+ }
+
+ //Write the CPU LP0 reset vector address in SCRATCH41
+ writel(virt_to_phys(tegra_lp2_startup), pmc + PMC_SCRATCH41);
}
diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c
index c0e944c79364..240ab30b1793 100644
--- a/arch/arm/mach-tegra/suspend.c
+++ b/arch/arm/mach-tegra/suspend.c
@@ -78,6 +78,7 @@ static void __iomem *tmrus = IO_ADDRESS(TEGRA_TMRUS_BASE);
#define PMC_SW_WAKE_STATUS 0x18
#define PMC_COREPWRGOOD_TIMER 0x3c
+#define PMC_SCRATCH0 0x50
#define PMC_SCRATCH1 0x54
#define PMC_CPUPWRGOOD_TIMER 0xc8
#define PMC_CPUPWROFF_TIMER 0xcc
@@ -194,6 +195,7 @@ static noinline void restore_cpu_complex(void)
}
extern unsigned long tegra_pgd_phys;
+extern unsigned int s_AvpWarmbootEntry;
static noinline void suspend_cpu_complex(void)
{
@@ -279,6 +281,19 @@ static void pmc_32kwritel(u32 val, unsigned long offs)
udelay(130);
}
+static void tegra_setup_warmboot(void)
+{
+ u32 scratch0;
+
+ //Turn the WARMBOOT flag on in scratch0
+ scratch0 = readl(pmc + PMC_SCRATCH0);
+ scratch0 |= 1;
+ pmc_32kwritel(scratch0, PMC_SCRATCH0);
+
+ //Write the AVP warmboot entry address in SCRATCH1
+ pmc_32kwritel(s_AvpWarmbootEntry, PMC_SCRATCH1);
+}
+
static void tegra_setup_wakepads(bool lp0_ok)
{
u32 temp, status, lvl;
@@ -290,10 +305,9 @@ static void tegra_setup_wakepads(bool lp0_ok)
pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
temp = readl(pmc + PMC_CTRL);
temp |= PMC_CTRL_LATCH_WAKEUPS;
- pmc_32kwritel(0, PMC_CTRL);
+ pmc_32kwritel(temp, PMC_CTRL);
temp &= ~PMC_CTRL_LATCH_WAKEUPS;
- pmc_32kwritel(0, PMC_CTRL);
-
+ pmc_32kwritel(temp, PMC_CTRL);
status = readl(pmc + PMC_SW_WAKE_STATUS);
lvl = readl(pmc + PMC_WAKE_LEVEL);
@@ -304,8 +318,8 @@ static void tegra_setup_wakepads(bool lp0_ok)
lvl |= pdata->wake_high;
lvl ^= status;
- writel(lvl, PMC_WAKE_LEVEL);
- writel(pdata->wake_enb, PMC_WAKE_MASK);
+ writel(lvl, pmc + PMC_WAKE_LEVEL);
+ writel(pdata->wake_enb, pmc + PMC_WAKE_MASK);
}
extern void __tegra_lp1_reset(void);
@@ -314,6 +328,7 @@ extern void __tegra_iram_end(void);
static u8 *iram_save = NULL;
static unsigned int iram_save_size = 0;
static void __iomem *iram_code = IO_ADDRESS(TEGRA_IRAM_CODE_AREA);
+static void __iomem *iram_avp_resume = IO_ADDRESS(TEGRA_IRAM_BASE);
static void tegra_suspend_dram(bool lp0_ok)
{
@@ -344,6 +359,7 @@ static void tegra_suspend_dram(bool lp0_ok)
} else {
NvRmPrivPowerSetState(s_hRmGlobal, NvRmPowerState_LP0);
set_power_timers(pdata->cpu_timer, pdata->cpu_off_timer);
+ tegra_setup_warmboot();
mode |= TEGRA_POWER_SYSCLK_OE;
mode |= TEGRA_POWER_PWRREQ_OE;
mode |= TEGRA_POWER_EFFECT_LP0;
@@ -365,6 +381,8 @@ static void tegra_suspend_dram(bool lp0_ok)
reg |= ((mode & TEGRA_POWER_PMC_MASK) << TEGRA_POWER_PMC_SHIFT);
pmc_32kwritel(reg, PMC_CTRL);
}
+ else
+ mode |= TEGRA_POWER_CPU_PWRREQ_OE;
tegra_setup_wakepads(lp0_ok);
suspend_cpu_complex();
@@ -390,7 +408,9 @@ static void tegra_suspend_dram(bool lp0_ok)
} else if (!lp0_ok)
writel(lp2_timer, pmc + PMC_CPUPWRGOOD_TIMER);
- memcpy(iram_code, iram_save, iram_save_size);
+ if (!lp0_ok)
+ memcpy(iram_code, iram_save, iram_save_size);
+
wmb();
}
@@ -489,6 +509,11 @@ static int tegra_suspend_prepare_late(void)
__func__, e);
return -EIO;
}
+
+ //The AVP stores its resume address in the first word of IRAM
+ //Write this resume address to SCRATCH39, where the warmboot
+ //code can later find it
+ writel(*(volatile unsigned int *)iram_avp_resume, pmc + PMC_SCRATCH39);
#endif
disable_irq(INT_SYS_STATS_MON);
return tegra_iovmm_suspend();
diff --git a/arch/arm/mach-tegra/tegra2_save.S b/arch/arm/mach-tegra/tegra2_save.S
index 6f7fd086a366..b5353803e0b5 100644
--- a/arch/arm/mach-tegra/tegra2_save.S
+++ b/arch/arm/mach-tegra/tegra2_save.S
@@ -69,6 +69,9 @@
#define FLOW_CTRL_HALT_CPU_EVENTS 0x0
+#define DEBUG_FORCE_RTC_WAKEUP_SEC 0
+#define RTC_PA_BASE 0x7000e000
+
#include "power-macros.S"
.macro emc_device_mask, rd, base
@@ -366,6 +369,33 @@ __tear_down_master_pll_cpu:
bic r0, r0, #(1<<30)
str r0, [r5, #CLK_RESET_PLLC_BASE]
+#if DEBUG_FORCE_RTC_WAKEUP_SEC
+ //r0 = RTC_BASE
+ mov32 r0, RTC_PA_BASE
+ //setup rtc wake
+ ldr r2, [r0, #0x10] /* milli */
+ ldr r2, [r0, #0x8] /* shadow */
+
+ add r2, r2, #DEBUG_FORCE_RTC_WAKEUP_SEC
+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]
+ str r2, [r0, #0x2c]
+rtc_idle3:
+ ldr r1, [r0, #0x4]
+ tst r1, #0x1
+ bne rtc_idle3
+#endif
+
__cclk_burst_set:
mov r0, #(4<<29) /* STOP_UNTIL_IRQ */
orr r0, r0, #(1<<10) | (1<<8) /* IRQ_0, FIQ_0 */