Patchwork [1/8] ARM: tegra: add common resume handling code for LP1 resuming

login
register
mail settings
Submitter Joseph Lo
Date July 26, 2013, 9:15 a.m.
Message ID <1374830110-30685-2-git-send-email-josephl@nvidia.com>
Download mbox | patch
Permalink /patch/262091/
State Superseded, archived
Headers show

Comments

Joseph Lo - July 26, 2013, 9:15 a.m.
The common LP1 resuming procedures of LP1 on Tegra was checking the LP1
mask first. The LP1 mask indicated that the Tegra device was in LP1 then
we need to resume the Tegra from the LP1 reset handler.

And the LP1 was putting the SDRAM to self-refresh mode, the SDRAM wasn't
accessible when resuming from LP1. We need to copy the LP1 reset handler
to IRAM before suspending. That's why you can see the address of LP1
reset handler was located in IRAM.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/reset-handler.S | 13 +++++++++++++
 arch/arm/mach-tegra/reset.c         |  2 ++
 arch/arm/mach-tegra/sleep.h         |  2 ++
 3 files changed, 17 insertions(+)
Stephen Warren - July 29, 2013, 10:38 p.m.
On 07/26/2013 03:15 AM, Joseph Lo wrote:
> The common LP1 resuming procedures of LP1 on Tegra was checking the LP1
> mask first. The LP1 mask indicated that the Tegra device was in LP1 then
> we need to resume the Tegra from the LP1 reset handler.
> 
> And the LP1 was putting the SDRAM to self-refresh mode, the SDRAM wasn't
> accessible when resuming from LP1. We need to copy the LP1 reset handler
> to IRAM before suspending. That's why you can see the address of LP1
> reset handler was located in IRAM.

That's rather hard to understand. How about:

==========
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.
==========

Talking about *copying* the LP1 resume code to IRAM isn't appropriate
here, since nothing in this patch performs any copying of the resume code.

> diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S

> @@ -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)]
> + THUMB(	add	lr, lr, #1 )			@ switch to Thumb mode
> +	cmp	lr, #0
> +	bleq	__die				@ no LP1 startup handler

On thumb, lr==#1 at this point. I think you want to move the THUMB()
instruction after the bleq.

> diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h

> +#define TEGRA_IRAM_CODE_AREA	(TEGRA_IRAM_BASE + SZ_4K)

The layout of IRAM should be described in irammap.h not sleep.h.
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 34614bd..492b10f 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -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)]
+ THUMB(	add	lr, lr, #1 )			@ switch to Thumb mode
+	cmp	lr, #0
+	bleq	__die				@ no LP1 startup handler
+	bx	lr
+__is_not_lp1:
+
 	/* Waking up from LP2? */
 	ldr	r9, [r12, #RESET_DATA(MASK_LP2)]
 	tst	r9, r11				@ if in_lp2
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 1ac434e..fd0bbf8 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -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
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index e907e40..e7f8b6f 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -29,6 +29,8 @@ 
 					+ IO_APB_VIRT)
 #define TEGRA_PMC_VIRT	(TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
 
+#define TEGRA_IRAM_CODE_AREA	(TEGRA_IRAM_BASE + SZ_4K)
+
 /* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
 #define PMC_SCRATCH37	0x130
 #define PMC_SCRATCH38	0x134