[PATCH 1/4] AM3517 : support for suspend/resume

Abhilash K V abhilash.kv at ti.com
Fri Aug 19 07:55:24 EDT 2011


1. Patch to disable dynamic sleep (as it is not supported
   on AM35xx).
2. Imported the unique suspend/resume sequence for AM3517,
   contained in the new file arch/arm/mach-omap2/sleep3517.S.
3. Added omap3517_ to symbol-names in sleep3517.S which are common
   with sleep34xx.S, and added appropriate checks.

There are still 3 caveats:

1. If "no_console_suspend" is enabled (via boot-args), the device
   doesnot resume but simply hangs.
2. Every second and subsequent attempt to suspend/resume prints this slow-path
   WARNING (for both uart1 and uart2), while resuming :
   [   70.943939] omap_hwmod: uart1: idle state can only be entered from
   enabled state
3. Wakeup using the TSC2004 touch-screen controller is not supported.

Signed-off-by: Ranjith Lohithakshan <ranjithl at ti.com>
Reviewed-by: Vaibhav Hiremath <hvaibhav at ti.com>
Signed-off-by: Abhilash K V <abhilash.kv at ti.com>
---
 arch/arm/mach-omap2/Makefile    |    2 +-
 arch/arm/mach-omap2/control.c   |    7 ++-
 arch/arm/mach-omap2/control.h   |    1 +
 arch/arm/mach-omap2/pm.h        |    4 +
 arch/arm/mach-omap2/pm34xx.c    |   18 ++++-
 arch/arm/mach-omap2/sleep3517.S |  144 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 170 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sleep3517.S

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 46f5fbc..3fdf086 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -61,7 +61,7 @@ endif
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o \
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o sleep3517.o \
 					   cpuidle34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index da53ba3..7d2d8a8 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -284,10 +284,13 @@ void omap3_save_scratchpad_contents(void)
 	 * The restore pointer is stored into the scratchpad.
 	 */
 	scratchpad_contents.boot_config_ptr = 0x0;
-	if (cpu_is_omap3630())
+	if (cpu_is_omap3505() || cpu_is_omap3517()) {
+		scratchpad_contents.public_restore_ptr =
+			virt_to_phys(omap3517_get_restore_pointer());
+	} else if (cpu_is_omap3630()) {
 		scratchpad_contents.public_restore_ptr =
 			virt_to_phys(get_omap3630_restore_pointer());
-	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
+	} else if (omap_rev() != OMAP3430_REV_ES3_0 &&
 					omap_rev() != OMAP3430_REV_ES3_1)
 		scratchpad_contents.public_restore_ptr =
 			virt_to_phys(get_restore_pointer());
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index ad024df..3003940 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -389,6 +389,7 @@ extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
 extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
 extern u32 *get_restore_pointer(void);
+extern u32 *omap3517_get_restore_pointer(void);
 extern u32 *get_es3_restore_pointer(void);
 extern u32 *get_omap3630_restore_pointer(void);
 extern u32 omap3_arm_context[128];
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 5c2bd2f..d773e07 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -77,13 +77,17 @@ extern void omap24xx_idle_loop_suspend(void);
 extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
 					void __iomem *sdrc_power);
 extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void omap3517_cpu_suspend(u32 *addr, int save_state);
 extern int save_secure_ram_context(u32 *addr);
+extern void omap3517_save_secure_ram_context(u32 *addr);
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
 extern unsigned int save_secure_ram_context_sz;
+extern unsigned int omap3517_save_secure_ram_context_sz;
 extern unsigned int omap24xx_cpu_suspend_sz;
 extern unsigned int omap34xx_cpu_suspend_sz;
+extern unsigned int omap3517_cpu_suspend_sz;
 
 #define PM_RTA_ERRATUM_i608		(1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 96a7624..12af5b9 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -497,6 +497,8 @@ console_still_active:
 
 int omap3_can_sleep(void)
 {
+	if (cpu_is_omap3505() || cpu_is_omap3517())
+		return 0;
 	if (!omap_uart_can_sleep())
 		return 0;
 	return 1;
@@ -848,11 +850,21 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 
 void omap_push_sram_idle(void)
 {
-	_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
+	if (cpu_is_omap3505() || cpu_is_omap3517())
+		_omap_sram_idle = omap_sram_push(omap3517_cpu_suspend,
+					omap3517_cpu_suspend_sz);
+	else
+		_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
 					omap34xx_cpu_suspend_sz);
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
-		_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
-				save_secure_ram_context_sz);
+		if (cpu_is_omap3505() || cpu_is_omap3517())
+			_omap_save_secure_sram = omap_sram_push(
+					omap3517_save_secure_ram_context,
+					omap3517_save_secure_ram_context_sz);
+		else
+			_omap_save_secure_sram = omap_sram_push(
+					save_secure_ram_context,
+					save_secure_ram_context_sz);
 }
 
 static void __init pm_errata_configure(void)
diff --git a/arch/arm/mach-omap2/sleep3517.S b/arch/arm/mach-omap2/sleep3517.S
new file mode 100644
index 0000000..3fceefc
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep3517.S
@@ -0,0 +1,144 @@
+/*
+/* linux/arch/arm/mach-omap2/sleep3517.S
+ *
+ * AM3505/3517 Sleep Code.
+ * Ranjith Lohithakshan <ranjithl at ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <plat/sram.h>
+#include <mach/io.h>
+
+#include "cm2xxx_3xxx.h"
+#include "prm2xxx_3xxx.h"
+#include "sdrc.h"
+#include "control.h"
+
+#define CM_IDLEST1_CORE_V OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
+#define CM_CLKST_CORE_V   OMAP34XX_CM_REGADDR(CORE_MOD, OMAP3430_CM_CLKSTST)
+#define CM_ICLKEN1_CORE_V OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
+
+#define EMIF_PM_CTR_V           OMAP2_L3_IO_ADDRESS(0x6D000038)
+#define OMAP3517_CONF1_REG_V    OMAP2_L4_IO_ADDRESS(0x48002584)
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap34xx_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap3517_cpu_suspend)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+loop:
+	/*b	loop*/	@Enable to debug by stepping through code
+
+	/* Put EMIF in self-refresh */
+	ldr     r4, emif_pm_ctrl
+	ldr     r5, [r4]
+	orr     r5, r5, #0x200
+	str     r5, [r4]
+
+	/* Disable SDRC and Control Module */
+	ldr     r4, cm_iclken1_core
+	ldr     r5, clk_core_disable
+	str     r5, [r4]
+wait_sdrc_ok:
+	ldr     r4, cm_idlest1_core
+	ldr     r5, [r4]
+	and     r5, r5, #0x2
+	cmp     r5, #0x2
+	bne     wait_sdrc_ok
+
+	/* Gate DDR Phy clock */
+	ldr     r4, omap3517_conf1
+	ldr     r5, emif_phy_gate
+	str     r5, [r4]
+
+	/* Data memory barrier and Data sync barrier */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+
+	wfi
+
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* Enable SDRC and Control Module */
+	ldr     r4, cm_iclken1_core
+	ldr     r5, iclk_core_enable
+	str     r5, [r4]
+
+	/* Enable DDR Phy Clock */
+	ldr     r4, omap3517_conf1
+	ldr     r5, emif_phy_enable
+	str     r5, [r4]
+
+	/* Take EMIF out of self-refresh */
+	ldr     r4, emif_pm_ctrl
+	ldr     r5, [r4]
+	bic     r5, r5, #0x200
+	str     r5, [r4]
+
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+
+clk_core_disable:
+	.word   0x0
+iclk_core_enable:
+	.word   0x42
+emif_phy_gate:
+	.word   0x2620
+emif_phy_enable:
+	.word   0x8620
+cm_idlest1_core:
+	.word   CM_IDLEST1_CORE_V
+cm_clkst_core:
+	.word   CM_CLKST_CORE_V
+emif_pm_ctrl:
+	.word   EMIF_PM_CTR_V
+cm_iclken1_core:
+	.word   CM_ICLKEN1_CORE_V
+omap3517_conf1:
+	.word   OMAP3517_CONF1_REG_V
+ENTRY(omap3517_cpu_suspend_sz)
+	.word	. - omap3517_cpu_suspend
+
+/* Function to call rom code to save secure ram context */
+ENTRY(omap3517_save_secure_ram_context)
+	stmfd   sp!, {r1-r12, lr}   @ save registers on stack
+save_secure_ram_debug:
+	/* b save_secure_ram_debug */   @ enable to debug save code
+	ldmfd   sp!, {r1-r12, pc}
+ENTRY(omap3517_save_secure_ram_context_sz)
+	.word   . - omap3517_save_secure_ram_context
+
+/* Function call to get the restore pointer for resume from OFF */
+ENTRY(omap3517_get_restore_pointer)
+	stmfd   sp!, {lr}     @ save registers on stack
+	ldmfd   sp!, {pc}     @ restore regs and return
+ENTRY(omap3517_get_restore_pointer_sz)
+	.word   . - omap3517_get_restore_pointer
+
-- 
1.7.1




More information about the linux-arm-kernel mailing list