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@xxxxxx> Reviewed-by: Vaibhav Hiremath <hvaibhav@xxxxxx> Signed-off-by: Abhilash K V <abhilash.kv@xxxxxx> --- 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@xxxxxx> + * + * 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 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html