Skip to contentSkip to conversation

ARM: tegra: support LP1 suspend mode

PATCH New Joseph Lo 2 participants 12 messages Aug 12, 2013 – Aug 13, 2013

Subsystems (6)
lore
Share & tools
lore

Joseph Lo

author
#0 lore raw

v3 cover ARM: tegra: support LP1 suspend mode

This series adds the support of LP1 suspend mode for Tegra.

V3:
* setting up CCLK burst policy to PLLX in LP1 resume code for Tegra114 too
* moving the CCLKG burst policy resume code to tegra_cpu_car_ops for Tegra114 V2:
* double confirm each patch can be built with all the combination of Tegra SoCs by bisect
* and make sure the function is still OK with above testing

Verified on Seaboard, Cardhu and Dalmore.
And tested with THUMB2_KERNEL as well.

P.S.
A known issue on Dalmore, the LP1 resume may take 10 ~ 15 seconds due to the 792MHz BCT. It can't be reproduced on Seaboard or Cardhu. And the root cause of this is about the default settings of EMC registers that cause the DRAM can't leave self-refresh mode immediately. If you want to test with quick LP1 resume on Dalmore, I can provide another HACK for this.

Joseph Lo (8):
ARM: tegra: add common resume handling code for LP1 resuming
ARM: tegra: config the polarity of the request of sys clock
clk: tegra114: add LP1 suspend/resume support
ARM: tegra: add common LP1 suspend support
ARM: tegra: add LP1 suspend support for Tegra30
ARM: tegra: add LP1 suspend support for Tegra20
ARM: tegra: add LP1 suspend support for Tegra114
ARM: tegra: enable LP1 suspend mode

 arch/arm/boot/dts/tegra114-dalmore.dts     |   2 +-
 arch/arm/boot/dts/tegra20-colibri-512.dtsi |   2 +-
 arch/arm/boot/dts/tegra20-harmony.dts      |   2 +-
 arch/arm/boot/dts/tegra20-paz00.dts        |   2 +-
 arch/arm/boot/dts/tegra20-seaboard.dts     |   2 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi    |   2 +-
 arch/arm/boot/dts/tegra20-trimslice.dts    |   2 +-
 arch/arm/boot/dts/tegra20-ventana.dts      |   2 +-
 arch/arm/boot/dts/tegra20-whistler.dts     |   2 +-
 arch/arm/boot/dts/tegra30-beaver.dts       |   2 +-
 arch/arm/boot/dts/tegra30-cardhu.dtsi      |   2 +-
 arch/arm/mach-tegra/Makefile               |   3 +
 arch/arm/mach-tegra/iomap.h                |   8 +
 arch/arm/mach-tegra/pm-tegra20.c           |  34 ++
 arch/arm/mach-tegra/pm-tegra30.c           |  34 ++
 arch/arm/mach-tegra/pm.c                   | 138 ++++++-
 arch/arm/mach-tegra/pm.h                   |  12 +
 arch/arm/mach-tegra/pmc.c                  |  37 ++
 arch/arm/mach-tegra/pmc.h                  |   3 +
 arch/arm/mach-tegra/reset-handler.S        |  13 +
 arch/arm/mach-tegra/reset.c                |   2 +
 arch/arm/mach-tegra/reset.h                |   4 +
 arch/arm/mach-tegra/sleep-tegra20.S        | 296 ++++++++++++++
 arch/arm/mach-tegra/sleep-tegra30.S        | 607 +++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.S                |   8 +-
 arch/arm/mach-tegra/sleep.h                |   8 +
 drivers/clk/tegra/clk-tegra114.c           |  12 +
 27 files changed, 1221 insertions(+), 20 deletions(-)
 create mode 100644 arch/arm/mach-tegra/pm-tegra20.c
 create mode 100644 arch/arm/mach-tegra/pm-tegra30.c
Signature · 1 line
1.8.3.4
author
#1 lore raw

PATCH v3 1/8 ARM: tegra: add common resume handling code for LP1 resuming

Add support to the Tegra CPU reset vector to detect whether the CPU is resuming from LP1 suspend state. If it is, branch to the LP1-specific resume code.

When Tegra enters the LP1 suspend state, the SDRAM controller is placed into a self-refresh state. For this reason, we must place the LP1 resume code into IRAM, so that it is accessible before SDRAM access has been re-enabled.

---
V3:
* no change
V2:
* update the commit message
* move the define of IRAM_CODE_AREA to iomap.h
* move the THUMB marco code before the 'bx' instruction

---
 arch/arm/mach-tegra/iomap.h         |  2 ++
 arch/arm/mach-tegra/reset-handler.S | 13 +++++++++++++
 arch/arm/mach-tegra/reset.c         |  2 ++
 3 files changed, 17 insertions(+)
arch/arm/mach-tegra/iomap.h +2 -0
index 399fbca..f2bdcb4 100644
@@ -24,6 +24,8 @@
 #define TEGRA_IRAM_BASE			0x40000000
 #define TEGRA_IRAM_SIZE			SZ_256K
 
+#define TEGRA_IRAM_CODE_AREA		(TEGRA_IRAM_BASE + SZ_4K)
+
 #define TEGRA_HOST1X_BASE		0x50000000
 #define TEGRA_HOST1X_SIZE		0x24000
 
arch/arm/mach-tegra/reset-handler.S +13 -0
index 34614bd..f527b2c 100644
@@ -182,6 +182,19 @@ after_errata:
 1:
 #endif
 
+	/* Waking up from LP1? */
+	ldr	r8, [r12, #RESET_DATA(MASK_LP1)]
+	tst	r8, r11				@ if in_lp1
+	beq	__is_not_lp1
+	cmp	r10, #0
+	bne	__die				@ only CPU0 can be here
+	ldr	lr, [r12, #RESET_DATA(STARTUP_LP1)]
+	cmp	lr, #0
+	bleq	__die				@ no LP1 startup handler
+ THUMB(	add	lr, lr, #1 )			@ switch to Thumb mode
+	bx	lr
+__is_not_lp1:
+
 	/* Waking up from LP2? */
 	ldr	r9, [r12, #RESET_DATA(MASK_LP2)]
 	tst	r9, r11				@ if in_lp2
arch/arm/mach-tegra/reset.c +2 -0
index 1ac434e..fd0bbf8 100644
@@ -81,6 +81,8 @@ void __init tegra_cpu_reset_handler_init(void)
 #endif
 
 #ifdef CONFIG_PM_SLEEP
+	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] =
+		TEGRA_IRAM_CODE_AREA;
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
 		virt_to_phys((void *)tegra_resume);
 #endif
Signature · 1 line
1.8.3.4
author
#2 lore raw

PATCH v3 2/8 ARM: tegra: config the polarity of the request of sys clock

In reply to Joseph Lo

When suspending to LP1 mode, the SYSCLK will be clock gated. And different board may have different polarity of the request of SYSCLK, this patch configure the polarity from the DT for the board.

---
V3:
* no change
V2:
* s/inverts/polarity/

---
 arch/arm/mach-tegra/pmc.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
arch/arm/mach-tegra/pmc.c +16 -0
index 8345fcd..03e6405 100644
@@ -27,6 +27,8 @@
 #include "pmc.h"
 #include "sleep.h"
 
+#define TEGRA_POWER_SYSCLK_POLARITY	(1 << 10)  /* sys clk polarity */
+#define TEGRA_POWER_SYSCLK_OE		(1 << 11)  /* system clock enable */
 #define TEGRA_POWER_EFFECT_LP0		(1 << 14)  /* LP0 when CPU pwr gated */
 #define TEGRA_POWER_CPU_PWRREQ_POLARITY	(1 << 15)  /* CPU pwr req polarity */
 #define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
@@ -238,6 +240,20 @@ void tegra_pmc_suspend_init(void)
 	reg = tegra_pmc_readl(PMC_CTRL);
 	reg |= TEGRA_POWER_CPU_PWRREQ_OE;
 	tegra_pmc_writel(reg, PMC_CTRL);
+
+	reg = tegra_pmc_readl(PMC_CTRL);
+
+	if (!pmc_pm_data.sysclkreq_high)
+		reg |= TEGRA_POWER_SYSCLK_POLARITY;
+	else
+		reg &= ~TEGRA_POWER_SYSCLK_POLARITY;
+
+	/* configure the output polarity while the request is tristated */
+	tegra_pmc_writel(reg, PMC_CTRL);
+
+	/* now enable the request */
+	reg |= TEGRA_POWER_SYSCLK_OE;
+	tegra_pmc_writel(reg, PMC_CTRL);
 }
 #endif
 
Signature · 1 line
1.8.3.4
author
#3 lore raw

PATCH v3 3/8 clk: tegra114: add LP1 suspend/resume support

In reply to Joseph Lo

When the system suspends to LP1, the CPU clock source is switched to CLK_M (12MHz Oscillator) during suspend/resume flow. The CPU clock source is controlled by the CCLKG_BURST_POLICY register, and hence this register must be restored during LP1 resume.

Cc Mike Turquette <[email protected]>

---
V3:
* move the CCLKG burst policy resume code to tegra_cpu_car_ops V2:
* update the commit message

---
 drivers/clk/tegra/clk-tegra114.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/clk/tegra/clk-tegra114.c +12 -0
index f74ed19..806d803 100644
@@ -293,6 +293,8 @@
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
 	u32 clk_csite_src;
+	u32 cclkg_burst;
+	u32 cclkg_divider;
 } tegra114_cpu_clk_sctx;
 #endif
 
@@ -2155,12 +2157,22 @@ static void tegra114_cpu_clock_suspend(void)
 	tegra114_cpu_clk_sctx.clk_csite_src =
 				readl(clk_base + CLK_SOURCE_CSITE);
 	writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+
+	tegra114_cpu_clk_sctx.cclkg_burst =
+				readl(clk_base + CCLKG_BURST_POLICY);
+	tegra114_cpu_clk_sctx.cclkg_divider =
+				readl(clk_base + CCLKG_BURST_POLICY + 4);
 }
 
 static void tegra114_cpu_clock_resume(void)
 {
 	writel(tegra114_cpu_clk_sctx.clk_csite_src,
 					clk_base + CLK_SOURCE_CSITE);
+
+	writel(tegra114_cpu_clk_sctx.cclkg_burst,
+					clk_base + CCLKG_BURST_POLICY);
+	writel(tegra114_cpu_clk_sctx.cclkg_divider,
+					clk_base + CCLKG_BURST_POLICY + 4);
 }
 #endif
 
Signature · 1 line
1.8.3.4
author
#4 lore raw

PATCH v3 4/8 ARM: tegra: add common LP1 suspend support

In reply to Joseph Lo

The LP1 suspending mode on Tegra means CPU rail off, devices and PLLs are clock gated and SDRAM in self-refresh mode. That means the low level LP1 suspending and resuming code couldn't be run on DRAM and the CPU must switch to the always on clock domain (a.k.a. CLK_M 12MHz oscillator). And the system clock (SCLK) would be switched to CLK_S, a 32KHz oscillator. The LP1 low level handling code need to be moved to IRAM area first. And marking the LP1 mask for indicating the Tegra device is in LP1. The CPU power timer needs to be re-calculated based on 32KHz that was originally based on PCLK.

When resuming from LP1, the LP1 reset handler will resume PLLs and then put DRAM to normal mode. Then jumping to the "tegra_resume" that will restore full context before back to kernel. The "tegra_resume" handler was expected to be found in PMC_SCRATCH41 register.

This is common LP1 procedures for Tegra, so we do these jobs mainly in this patch:
* moving LP1 low level handling code to IRAM
* marking LP1 mask
* copying the physical address of "tegra_resume" to PMC_SCRATCH41
* re-calculate the CPU power timer based on 32KHz

---
V3:
* using a "#define" of IRAM_CODE to replace original static variable V2:
* don't duplicate tegraXX_lp1_iram for different SoC
* unify the suspend func call to cpu_suspend with "tegra_sleep_func"

---
 arch/arm/mach-tegra/pm.c    | 108 ++++++++++++++++++++++++++++++++++++++++++--
 arch/arm/mach-tegra/pm.h    |   7 +++
 arch/arm/mach-tegra/pmc.c   |  21 +++++++++
 arch/arm/mach-tegra/pmc.h   |   3 ++
 arch/arm/mach-tegra/reset.h |   4 ++
 5 files changed, 138 insertions(+), 5 deletions(-)
arch/arm/mach-tegra/pm.c +103 -5
index 5792872..d12385f 100644
@@ -37,12 +37,19 @@
 #include "reset.h"
 #include "flowctrl.h"
 #include "fuse.h"
+#include "pm.h"
 #include "pmc.h"
 #include "sleep.h"
 
 #ifdef CONFIG_PM_SLEEP
+#define IRAM_CODE IO_ADDRESS(TEGRA_IRAM_CODE_AREA)
 static DEFINE_SPINLOCK(tegra_lp2_lock);
+static u32 iram_save_size;
+static void *iram_save_addr;
+struct tegra_lp1_iram tegra_lp1_iram;
 void (*tegra_tear_down_cpu)(void);
+void (*tegra_sleep_core_finish)(unsigned long v2p);
+static int (*tegra_sleep_func)(unsigned long v2p);
 
 static void tegra_tear_down_cpu_init(void)
 {
@@ -174,14 +181,75 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 				enum tegra_suspend_mode mode)
 {
 	/*
-	 * The Tegra devices only support suspending to LP2 currently.
+	 * The Tegra devices support suspending to LP1 or lower currently.
 	 */
-	if (mode > TEGRA_SUSPEND_LP2)
-		return TEGRA_SUSPEND_LP2;
+	if (mode > TEGRA_SUSPEND_LP1)
+		return TEGRA_SUSPEND_LP1;
 
 	return mode;
 }
 
+static int tegra_sleep_core(unsigned long v2p)
+{
+	setup_mm_for_reboot();
+	tegra_sleep_core_finish(v2p);
+
+	/* should never here */
+	BUG();
+
+	return 0;
+}
+
+/*
+ * tegra_lp1_iram_hook
+ *
+ * Hooking the address of LP1 reset vector and SDRAM self-refresh code in
+ * SDRAM. These codes not be copied to IRAM in this fuction. We need to
+ * copy these code to IRAM before LP0/LP1 suspend and restore the content
+ * of IRAM after resume.
+ */
+static bool tegra_lp1_iram_hook(void)
+{
+	if (!tegra_lp1_iram.start_addr || !tegra_lp1_iram.end_addr)
+		return false;
+
+	iram_save_size = tegra_lp1_iram.end_addr - tegra_lp1_iram.start_addr;
+	iram_save_addr = kmalloc(iram_save_size, GFP_KERNEL);
+	if (!iram_save_addr)
+		return false;
+
+	return true;
+}
+
+static bool tegra_sleep_core_init(void)
+{
+	if (!tegra_sleep_core_finish)
+		return false;
+
+	return true;
+}
+
+static void tegra_suspend_enter_lp1(void)
+{
+	tegra_pmc_suspend();
+
+	/* copy the reset vector & SDRAM shutdown code into IRAM */
+	memcpy(iram_save_addr, IRAM_CODE, iram_save_size);
+	memcpy(IRAM_CODE, tegra_lp1_iram.start_addr, iram_save_size);
+
+	*((u32 *)tegra_cpu_lp1_mask) = 1;
+}
+
+static void tegra_suspend_exit_lp1(void)
+{
+	tegra_pmc_resume();
+
+	/* restore IRAM */
+	memcpy(IRAM_CODE, iram_save_addr, iram_save_size);
+
+	*(u32 *)tegra_cpu_lp1_mask = 0;
+}
+
 static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
 	[TEGRA_SUSPEND_NONE] = "none",
 	[TEGRA_SUSPEND_LP2] = "LP2",
@@ -205,6 +273,9 @@ static int tegra_suspend_enter(suspend_state_t state)
 
 	suspend_cpu_complex();
 	switch (mode) {
+	case TEGRA_SUSPEND_LP1:
+		tegra_suspend_enter_lp1();
+		break;
 	case TEGRA_SUSPEND_LP2:
 		tegra_set_cpu_in_lp2();
 		break;
@@ -212,9 +283,12 @@ static int tegra_suspend_enter(suspend_state_t state)
 		break;
 	}
 
-	cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
+	cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
 	switch (mode) {
+	case TEGRA_SUSPEND_LP1:
+		tegra_suspend_exit_lp1();
+		break;
 	case TEGRA_SUSPEND_LP2:
 		tegra_clear_cpu_in_lp2();
 		break;
@@ -235,12 +309,36 @@ static const struct platform_suspend_ops tegra_suspend_ops = {
 
 void __init tegra_init_suspend(void)
 {
-	if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
+	enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
+
+	if (mode == TEGRA_SUSPEND_NONE)
 		return;
 
 	tegra_tear_down_cpu_init();
 	tegra_pmc_suspend_init();
 
+	if (mode >= TEGRA_SUSPEND_LP1) {
+		if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
+			pr_err("%s: unable to allocate memory for SDRAM"
+			       "self-refresh -- LP0/LP1 unavailable\n",
+			       __func__);
+			tegra_pmc_set_suspend_mode(TEGRA_SUSPEND_LP2);
+			mode = TEGRA_SUSPEND_LP2;
+		}
+	}
+
+	/* set up sleep function for cpu_suspend */
+	switch (mode) {
+	case TEGRA_SUSPEND_LP1:
+		tegra_sleep_func = tegra_sleep_core;
+		break;
+	case TEGRA_SUSPEND_LP2:
+		tegra_sleep_func = tegra_sleep_cpu;
+		break;
+	default:
+		break;
+	}
+
 	suspend_set_ops(&tegra_suspend_ops);
 }
 #endif
arch/arm/mach-tegra/pm.h +7 -0
index 94c4b9d..478706e 100644
@@ -23,6 +23,13 @@
 
 #include "pmc.h"
 
+struct tegra_lp1_iram {
+	void	*start_addr;
+	void	*end_addr;
+};
+extern struct tegra_lp1_iram tegra_lp1_iram;
+extern void (*tegra_sleep_core_finish)(unsigned long v2p);
+
 extern unsigned long l2x0_saved_regs_addr;
 
 void save_cpu_arch_register(void);
arch/arm/mach-tegra/pmc.c +21 -0
index 03e6405..8acb881 100644
@@ -196,6 +196,24 @@ enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
 	return pmc_pm_data.suspend_mode;
 }
 
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
+{
+	if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
+		return;
+
+	pmc_pm_data.suspend_mode = mode;
+}
+
+void tegra_pmc_suspend(void)
+{
+	tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
+}
+
+void tegra_pmc_resume(void)
+{
+	tegra_pmc_writel(0x0, PMC_SCRATCH41);
+}
+
 void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
 {
 	u32 reg, csr_reg;
@@ -219,6 +237,9 @@ void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
 	}
 
 	switch (mode) {
+	case TEGRA_SUSPEND_LP1:
+		rate = 32768;
+		break;
 	case TEGRA_SUSPEND_LP2:
 		rate = clk_get_rate(tegra_pclk);
 		break;
arch/arm/mach-tegra/pmc.h +3 -0
index e1c2df2..549f8c7 100644
@@ -28,6 +28,9 @@ enum tegra_suspend_mode {
 
 #ifdef CONFIG_PM_SLEEP
 enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
+void tegra_pmc_suspend(void);
+void tegra_pmc_resume(void);
 void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
 void tegra_pmc_suspend_init(void);
 #endif
arch/arm/mach-tegra/reset.h +4 -0
index c90d8e9..76a9343 100644
@@ -39,6 +39,10 @@ void __tegra_cpu_reset_handler_end(void);
 void tegra_secondary_startup(void);
 
 #ifdef CONFIG_PM_SLEEP
+#define tegra_cpu_lp1_mask \
+	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
+	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP1] - \
+	 (u32)__tegra_cpu_reset_handler_start)))
 #define tegra_cpu_lp2_mask \
 	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
 	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
Signature · 1 line
1.8.3.4
#5 lore raw

PATCH v3 4/8 ARM: tegra: add common LP1 suspend support

Quoted 22 lines · Joseph Lo

The LP1 suspending mode on Tegra means CPU rail off, devices and PLLs are clock gated and SDRAM in self-refresh mode. That means the low level LP1 suspending and resuming code couldn't be run on DRAM and the CPU must switch to the always on clock domain (a.k.a. CLK_M 12MHz oscillator). And the system clock (SCLK) would be switched to CLK_S, a 32KHz oscillator. The LP1 low level handling code need to be moved to IRAM area first. And marking the LP1 mask for indicating the Tegra device is in LP1. The CPU power timer needs to be re-calculated based on 32KHz that was originally based on PCLK.

When resuming from LP1, the LP1 reset handler will resume PLLs and then put DRAM to normal mode. Then jumping to the "tegra_resume" that will restore full context before back to kernel. The "tegra_resume" handler was expected to be found in PMC_SCRATCH41 register.

This is common LP1 procedures for Tegra, so we do these jobs mainly in this patch:
* moving LP1 low level handling code to IRAM
* marking LP1 mask
* copying the physical address of "tegra_resume" to PMC_SCRATCH41
* re-calculate the CPU power timer based on 32KHz

Quoted 4 lines

---
V3:
* using a "#define" of IRAM_CODE to replace original static variable

I didn't mean change the variable to a define, but rather simply to use the IO_ADDRESS() define instead of any new define. i.e.:

arch/arm/mach-tegra/pm.c line 45

Quoted 3 lines
arch/arm/mach-tegra/pm.c +1 -0
 
+#define IRAM_CODE IO_ADDRESS(TEGRA_IRAM_CODE_AREA)

... just don't add that, and ...

arch/arm/mach-tegra/pm.c enum tegra_suspend_mode tegra_pm_validate_suspend_mode( · line 238

Quoted 7 lines
arch/arm/mach-tegra/pm.c +7 -0
+static void tegra_suspend_enter_lp1(void)
+{
+	tegra_pmc_suspend();
+
+	/* copy the reset vector & SDRAM shutdown code into IRAM */
+	memcpy(iram_save_addr, IRAM_CODE, iram_save_size);
+	memcpy(IRAM_CODE, tegra_lp1_iram.start_addr, iram_save_size);

... and s/IRAM_CODE/IO_ADDRESS(TEGRA_IRAM_CODE_AREA)/ in that code.

I'll make that fixup when applying these patches.

author
#6 lore raw

PATCH v3 4/8 ARM: tegra: add common LP1 suspend support

Quoted 47 lines · Stephen Warren
Quoted 22 lines · Joseph Lo

The LP1 suspending mode on Tegra means CPU rail off, devices and PLLs are clock gated and SDRAM in self-refresh mode. That means the low level LP1 suspending and resuming code couldn't be run on DRAM and the CPU must switch to the always on clock domain (a.k.a. CLK_M 12MHz oscillator). And the system clock (SCLK) would be switched to CLK_S, a 32KHz oscillator. The LP1 low level handling code need to be moved to IRAM area first. And marking the LP1 mask for indicating the Tegra device is in LP1. The CPU power timer needs to be re-calculated based on 32KHz that was originally based on PCLK.

When resuming from LP1, the LP1 reset handler will resume PLLs and then put DRAM to normal mode. Then jumping to the "tegra_resume" that will restore full context before back to kernel. The "tegra_resume" handler was expected to be found in PMC_SCRATCH41 register.

This is common LP1 procedures for Tegra, so we do these jobs mainly in this patch:
* moving LP1 low level handling code to IRAM
* marking LP1 mask
* copying the physical address of "tegra_resume" to PMC_SCRATCH41
* re-calculate the CPU power timer based on 32KHz

Quoted 4 lines

---
V3:
* using a "#define" of IRAM_CODE to replace original static variable

I didn't mean change the variable to a define, but rather simply to use the IO_ADDRESS() define instead of any new define. i.e.:

arch/arm/mach-tegra/pm.c line 45

Quoted 3 lines
arch/arm/mach-tegra/pm.c +1 -0
 
+#define IRAM_CODE IO_ADDRESS(TEGRA_IRAM_CODE_AREA)

... just don't add that, and ...

arch/arm/mach-tegra/pm.c enum tegra_suspend_mode tegra_pm_validate_suspend_mode( · line 238

Quoted 7 lines
arch/arm/mach-tegra/pm.c +7 -0
+static void tegra_suspend_enter_lp1(void)
+{
+	tegra_pmc_suspend();
+
+	/* copy the reset vector & SDRAM shutdown code into IRAM */
+	memcpy(iram_save_addr, IRAM_CODE, iram_save_size);
+	memcpy(IRAM_CODE, tegra_lp1_iram.start_addr, iram_save_size);

... and s/IRAM_CODE/IO_ADDRESS(TEGRA_IRAM_CODE_AREA)/ in that code.

Quoted 1 line

I'll make that fixup when applying these patches.

OK. Thanks.

Joseph

author
#7 lore raw

PATCH v3 5/8 ARM: tegra: add LP1 suspend support for Tegra30

In reply to Joseph Lo

The LP1 suspend mode will power off the CPU, clock gated the PLLs and put SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The sequence when LP1 suspending:

* tunning off L1 data cache and the MMU
* storing some EMC registers, DPD (deep power down) status, clk source of mselect and SCLK burst policy
* putting SDRAM into self-refresh
* switching CPU to CLK_M (12MHz OSC)
* tunning off PLLM, PLLP, PLLA, PLLC and PLLX
* switching SCLK to CLK_S (32KHz OSC)
* shutting off the CPU rail

The sequence of LP1 resuming:

* re-enabling PLLM, PLLP, PLLA, PLLC and PLLX
* restoring the clk source of mselect and SCLK burst policy
* setting up CCLK burst policy to PLLX
* restoring DPD status and some EMC registers
* resuming SDRAM to normal mode
* jumping to the "tegra_resume" from PMC_SCRATCH41

Due to the SDRAM will be put into self-refresh mode, the low level procedures of LP1 suspending and resuming should be copied to TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) when suspending. Before restoring the CPU context when resuming, the SDRAM needs to be switched back to normal mode. And the PLLs need to be re-enabled, SCLK burst policy be restored, CCLK burst policy be set in PLLX. Then jumping to "tegra_resume" that was expected to be stored in PMC_SCRATCH41 to restore CPU context and back to kernel.

Based on the work by: Scott Williams <[email protected]>

---
V3:
* remove the no meaning message "AND MUST BE FIRST" V2:
* remove wait_for_us
* using IS_ENABLE for SoC specific code
* calculating "tegra30_sdram_pad_save" by assemby symbol

---
 arch/arm/mach-tegra/Makefile        |   1 +
 arch/arm/mach-tegra/pm-tegra30.c    |  34 +++
 arch/arm/mach-tegra/pm.c            |  18 ++
 arch/arm/mach-tegra/pm.h            |   3 +
 arch/arm/mach-tegra/sleep-tegra30.S | 492 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/sleep.S         |   8 +-
 arch/arm/mach-tegra/sleep.h         |   8 +
 7 files changed, 560 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/mach-tegra/pm-tegra30.c
arch/arm/mach-tegra/Makefile +1 -0
index 98b184e..d341980 100644
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
 endif
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= pm-tegra30.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= cpuidle-tegra30.o
 endif
arch/arm/mach-tegra/pm-tegra30.c new file +34 -0
new file mode 100644
index 0000000..8fa326d
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+
+#include "pm.h"
+
+#ifdef CONFIG_PM_SLEEP
+extern u32 tegra30_iram_start, tegra30_iram_end;
+extern void tegra30_sleep_core_finish(unsigned long);
+
+void tegra30_lp1_iram_hook(void)
+{
+	tegra_lp1_iram.start_addr = &tegra30_iram_start;
+	tegra_lp1_iram.end_addr = &tegra30_iram_end;
+}
+
+void tegra30_sleep_core_init(void)
+{
+	tegra_sleep_core_finish = tegra30_sleep_core_finish;
+}
+#endif
arch/arm/mach-tegra/pm.c +18 -0
index d12385f..d557159 100644
@@ -210,6 +210,15 @@ static int tegra_sleep_core(unsigned long v2p)
  */
 static bool tegra_lp1_iram_hook(void)
 {
+	switch (tegra_chip_id) {
+	case TEGRA30:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
+			tegra30_lp1_iram_hook();
+		break;
+	default:
+		break;
+	}
+
 	if (!tegra_lp1_iram.start_addr || !tegra_lp1_iram.end_addr)
 		return false;
 
@@ -223,6 +232,15 @@ static bool tegra_lp1_iram_hook(void)
 
 static bool tegra_sleep_core_init(void)
 {
+	switch (tegra_chip_id) {
+	case TEGRA30:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
+			tegra30_sleep_core_init();
+		break;
+	default:
+		break;
+	}
+
 	if (!tegra_sleep_core_finish)
 		return false;
 
arch/arm/mach-tegra/pm.h +3 -0
index 478706e..803bd53 100644
@@ -30,6 +30,9 @@ struct tegra_lp1_iram {
 extern struct tegra_lp1_iram tegra_lp1_iram;
 extern void (*tegra_sleep_core_finish)(unsigned long v2p);
 
+void tegra30_lp1_iram_hook(void);
+void tegra30_sleep_core_init(void);
+
 extern unsigned long l2x0_saved_regs_addr;
 
 void save_cpu_arch_register(void);
arch/arm/mach-tegra/sleep-tegra30.S +492 -0

521 lines not on this page · raw message

arch/arm/mach-tegra/sleep.S +4 -4
index 8388113..8d06213 100644
@@ -134,10 +134,10 @@ ENTRY(tegra_shut_off_mmu)
 #ifdef CONFIG_CACHE_L2X0
 	/* Disable L2 cache */
 	check_cpu_part_num 0xc09, r9, r10
-	movweq	r4, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000)
-	movteq	r4, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000)
-	moveq	r5, #0
-	streq	r5, [r4, #L2X0_CTRL]
+	movweq	r2, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000)
+	movteq	r2, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000)
+	moveq	r3, #0
+	streq	r3, [r2, #L2X0_CTRL]
 #endif
 	mov	pc, r0
 ENDPROC(tegra_shut_off_mmu)
arch/arm/mach-tegra/sleep.h +8 -0
index e907e40..a4edbb3 100644
@@ -46,6 +46,14 @@
 #define TEGRA_FLUSH_CACHE_ALL	1
 
 #ifdef __ASSEMBLY__
+/* waits until the microsecond counter (base) is > rn */
+.macro wait_until, rn, base, tmp
+	add	\rn, \rn, #1
+1001:	ldr	\tmp, [\base]
+	cmp	\tmp, \rn
+	bmi	1001b
+.endm
+
 /* returns the offset of the flow controller halt register for a cpu */
 .macro cpu_to_halt_reg rd, rcpu
 	cmp	\rcpu, #0
Signature · 1 line
1.8.3.4
author
#8 lore raw

PATCH v3 6/8 ARM: tegra: add LP1 suspend support for Tegra20

In reply to Joseph Lo

The LP1 suspend mode will power off the CPU, clock gated the PLLs and put SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The sequence when LP1 suspending:

* tunning off L1 data cache and the MMU
* putting SDRAM into self-refresh
* storing some EMC registers and SCLK burst policy
* switching CPU to CLK_M (12MHz OSC)
* switching SCLK to CLK_S (32KHz OSC)
* tunning off PLLM, PLLP and PLLC
* shutting off the CPU rail

The sequence of LP1 resuming:

* re-enabling PLLM, PLLP, and PLLC
* restoring some EMC registers and SCLK burst policy
* setting up CCLK burst policy to PLLP
* resuming SDRAM to normal mode
* jumping to the "tegra_resume" from PMC_SCRATCH41

Due to the SDRAM will be put into self-refresh mode, the low level procedures of LP1 suspending and resuming should be copied to TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) when suspending. Before restoring the CPU context when resuming, the SDRAM needs to be switched back to normal mode. And the PLLs need to be re-enabled, SCLK burst policy be restored, CCLK burst policy be set in PLLP. Then jumping to "tegra_resume" that was expected to be stored in PMC_SCRATCH41 to restore CPU context and back to kernel.

Based on the work by:
Colin Cross <[email protected]>
Gary King <[email protected]>

---
V3:
* switch SCLK burst policy reg to CLK_S after disabling PLLs to align with Tegra30/114
V2:
* using IS_ENABLE for SoC specific code
* calculating "tegra20_sdram_pad_save" by assembly symbol

---
 arch/arm/mach-tegra/Makefile        |   1 +
 arch/arm/mach-tegra/pm-tegra20.c    |  34 +++++
 arch/arm/mach-tegra/pm.c            |   8 +
 arch/arm/mach-tegra/pm.h            |   2 +
 arch/arm/mach-tegra/sleep-tegra20.S | 296 ++++++++++++++++++++++++++++++++++++
 5 files changed, 341 insertions(+)
 create mode 100644 arch/arm/mach-tegra/pm-tegra20.c
arch/arm/mach-tegra/Makefile +1 -0
index d341980..a3fe22d 100644
@@ -17,6 +17,7 @@ obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pm-tegra20.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
 endif
arch/arm/mach-tegra/pm-tegra20.c new file +34 -0
new file mode 100644
index 0000000..d65e1d7
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+
+#include "pm.h"
+
+#ifdef CONFIG_PM_SLEEP
+extern u32 tegra20_iram_start, tegra20_iram_end;
+extern void tegra20_sleep_core_finish(unsigned long);
+
+void tegra20_lp1_iram_hook(void)
+{
+	tegra_lp1_iram.start_addr = &tegra20_iram_start;
+	tegra_lp1_iram.end_addr = &tegra20_iram_end;
+}
+
+void tegra20_sleep_core_init(void)
+{
+	tegra_sleep_core_finish = tegra20_sleep_core_finish;
+}
+#endif
arch/arm/mach-tegra/pm.c +8 -0
index d557159..d2f736a 100644
@@ -211,6 +211,10 @@ static int tegra_sleep_core(unsigned long v2p)
 static bool tegra_lp1_iram_hook(void)
 {
 	switch (tegra_chip_id) {
+	case TEGRA20:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+			tegra20_lp1_iram_hook();
+		break;
 	case TEGRA30:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
 			tegra30_lp1_iram_hook();
@@ -233,6 +237,10 @@ static bool tegra_lp1_iram_hook(void)
 static bool tegra_sleep_core_init(void)
 {
 	switch (tegra_chip_id) {
+	case TEGRA20:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+			tegra20_sleep_core_init();
+		break;
 	case TEGRA30:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
 			tegra30_sleep_core_init();
arch/arm/mach-tegra/pm.h +2 -0
index 803bd53..fe204e5 100644
@@ -30,6 +30,8 @@ struct tegra_lp1_iram {
 extern struct tegra_lp1_iram tegra_lp1_iram;
 extern void (*tegra_sleep_core_finish)(unsigned long v2p);
 
+void tegra20_lp1_iram_hook(void);
+void tegra20_sleep_core_init(void);
 void tegra30_lp1_iram_hook(void);
 void tegra30_sleep_core_init(void);
 
arch/arm/mach-tegra/sleep-tegra20.S +296 -0

322 lines not on this page · raw message

Signature · 1 line
1.8.3.4
author
#9 lore raw

PATCH v3 7/8 ARM: tegra: add LP1 suspend support for Tegra114

In reply to Joseph Lo

The LP1 suspend mode will power off the CPU, clock gated the PLLs and put SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The sequence when LP1 suspending:

* tunning off L1 data cache and the MMU
* storing some EMC registers, DPD (deep power down) status, clk source of mselect and SCLK burst policy
* putting SDRAM into self-refresh
* switching CPU to CLK_M (12MHz OSC)
* tunning off PLLM, PLLP, PLLA, PLLC and PLLX
* switching SCLK to CLK_S (32KHz OSC)
* shutting off the CPU rail

The sequence of LP1 resuming:

* re-enabling PLLM, PLLP, PLLA, PLLC and PLLX
* restoring the clk source of mselect and SCLK burst policy
* setting up CCLK burst policy to PLLX
* restoring DPD status and some EMC registers
* resuming SDRAM to normal mode
* jumping to the "tegra_resume" from PMC_SCRATCH41

Due to the SDRAM will be put into self-refresh mode, the low level procedures of LP1 suspending and resuming should be copied to TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) when suspending. Before restoring the CPU context when resuming, the SDRAM needs to be switched back to normal mode. And the PLLs need to be re-enabled, SCLK burst policy be restored. Then jumping to "tegra_resume" that was expected to be stored in PMC_SCRATCH41 to restore CPU context and back to kernel.

Based on the work by: Bo Yan <[email protected]>

---
V3:
* setting up CCLK burst policy to PLLX in lp1_resume V2:
* using IS_ENABLE for SoC specific code
* moving the fix of PLL lock func to previous patch

---
 arch/arm/mach-tegra/Makefile        |   1 +
 arch/arm/mach-tegra/iomap.h         |   6 ++
 arch/arm/mach-tegra/pm.c            |   8 +-
 arch/arm/mach-tegra/sleep-tegra30.S | 141 ++++++++++++++++++++++++++++++++----
 4 files changed, 141 insertions(+), 15 deletions(-)
arch/arm/mach-tegra/Makefile +1 -0
index a3fe22d..f4e7063 100644
@@ -33,6 +33,7 @@ obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
 
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= tegra114_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= sleep-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= pm-tegra30.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
 endif
arch/arm/mach-tegra/iomap.h +6 -0
index f2bdcb4..aba3629 100644
@@ -239,6 +239,12 @@
 #define TEGRA_KFUSE_BASE		0x7000FC00
 #define TEGRA_KFUSE_SIZE		SZ_1K
 
+#define TEGRA_EMC0_BASE			0x7001A000
+#define TEGRA_EMC0_SIZE			SZ_2K
+
+#define TEGRA_EMC1_BASE			0x7001A800
+#define TEGRA_EMC1_SIZE			SZ_2K
+
 #define TEGRA_CSITE_BASE		0x70040000
 #define TEGRA_CSITE_SIZE		SZ_256K
 
arch/arm/mach-tegra/pm.c +6 -2
index d2f736a..dedb75b 100644
@@ -216,7 +216,9 @@ static bool tegra_lp1_iram_hook(void)
 			tegra20_lp1_iram_hook();
 		break;
 	case TEGRA30:
-		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
+	case TEGRA114:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
 			tegra30_lp1_iram_hook();
 		break;
 	default:
@@ -242,7 +244,9 @@ static bool tegra_sleep_core_init(void)
 			tegra20_sleep_core_init();
 		break;
 	case TEGRA30:
-		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC))
+	case TEGRA114:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
 			tegra30_sleep_core_init();
 		break;
 	default:
arch/arm/mach-tegra/sleep-tegra30.S +128 -13

257 lines not on this page · raw message

Signature · 1 line
1.8.3.4
author
#10 lore raw

PATCH v3 8/8 ARM: tegra: enable LP1 suspend mode

In reply to Joseph Lo

Enabling the LP1 suspend mode for Tegra devices.

---
V3:
* fix the "Tested-by" line
V2:
* no change

---
 arch/arm/boot/dts/tegra114-dalmore.dts     | 2 +-
 arch/arm/boot/dts/tegra20-colibri-512.dtsi | 2 +-
 arch/arm/boot/dts/tegra20-harmony.dts      | 2 +-
 arch/arm/boot/dts/tegra20-paz00.dts        | 2 +-
 arch/arm/boot/dts/tegra20-seaboard.dts     | 2 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi    | 2 +-
 arch/arm/boot/dts/tegra20-trimslice.dts    | 2 +-
 arch/arm/boot/dts/tegra20-ventana.dts      | 2 +-
 arch/arm/boot/dts/tegra20-whistler.dts     | 2 +-
 arch/arm/boot/dts/tegra30-beaver.dts       | 2 +-
 arch/arm/boot/dts/tegra30-cardhu.dtsi      | 2 +-
 11 files changed, 11 insertions(+), 11 deletions(-)
arch/arm/boot/dts/tegra114-dalmore.dts +1 -1
index b5a42f0..44873b5 100644
@@ -1024,7 +1024,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <500>;
 		nvidia,cpu-pwr-off-time = <300>;
 		nvidia,core-pwr-good-time = <641 3845>;
arch/arm/boot/dts/tegra20-colibri-512.dtsi +1 -1
index 2fcb3f2..06c5fa0 100644
@@ -363,7 +363,7 @@
 	};
 
 	pmc {
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <5000>;
 		nvidia,cpu-pwr-off-time = <5000>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-harmony.dts +1 -1
index d9f89cd..d44cf90 100644
@@ -417,7 +417,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <5000>;
 		nvidia,cpu-pwr-off-time = <5000>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-paz00.dts +1 -1
index cfd1276..8d71fc9 100644
@@ -417,7 +417,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <2000>;
 		nvidia,cpu-pwr-off-time = <0>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-seaboard.dts +1 -1
index 60137f5..c256c81 100644
@@ -518,7 +518,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <5000>;
 		nvidia,cpu-pwr-off-time = <5000>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-tamonten.dtsi +1 -1
index c54faae..f00febe 100644
@@ -459,7 +459,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <5000>;
 		nvidia,cpu-pwr-off-time = <5000>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-trimslice.dts +1 -1
index 906e07f..665e504 100644
@@ -302,7 +302,7 @@
 	};
 
 	pmc {
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <5000>;
 		nvidia,cpu-pwr-off-time = <5000>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-ventana.dts +1 -1
index 7f8c28d..aab872c 100644
@@ -494,7 +494,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <2000>;
 		nvidia,cpu-pwr-off-time = <100>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra20-whistler.dts +1 -1
index a6b1b5b..608b79a 100644
@@ -497,7 +497,7 @@
 
 	pmc {
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <2000>;
 		nvidia,cpu-pwr-off-time = <1000>;
 		nvidia,core-pwr-good-time = <0 3845>;
arch/arm/boot/dts/tegra30-beaver.dts +1 -1
index 87c5f7b..7378927 100644
@@ -262,7 +262,7 @@
 	pmc {
 		status = "okay";
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <2000>;
 		nvidia,cpu-pwr-off-time = <200>;
 		nvidia,core-pwr-good-time = <3845 3845>;
arch/arm/boot/dts/tegra30-cardhu.dtsi +1 -1
index c011b67..d78c90c 100644
@@ -314,7 +314,7 @@
 	pmc {
 		status = "okay";
 		nvidia,invert-interrupt;
-		nvidia,suspend-mode = <2>;
+		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <2000>;
 		nvidia,cpu-pwr-off-time = <200>;
 		nvidia,core-pwr-good-time = <3845 3845>;
Signature · 1 line
1.8.3.4
#11 lore raw

v3 cover ARM: tegra: support LP1 suspend mode

In reply to Joseph Lo
Quoted 1 line · Joseph Lo

This series adds the support of LP1 suspend mode for Tegra.

I have applied patches 1-7 to Tegra's for-3.12/soc and path 8 to Tegra's for-3.12/dt branch.