Commit d9d5cd4e authored by Tuukka Tikkanen's avatar Tuukka Tikkanen Committed by Tony Lindgren

ARM: OMAP: PM update

Sync with linux-omap tree. PM updates to make deep sleep work.
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent e88be4f3
...@@ -39,13 +39,18 @@ ...@@ -39,13 +39,18 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/arch/omap16xx.h> #include <asm/arch/irqs.h>
#include <asm/arch/tc.h>
#include <asm/arch/pm.h> #include <asm/arch/pm.h>
#include <asm/arch/mux.h> #include <asm/arch/mux.h>
#include <asm/arch/tc.h>
#include <asm/arch/tps65010.h> #include <asm/arch/tps65010.h>
#include "clock.h" #include "clock.h"
...@@ -63,7 +68,7 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; ...@@ -63,7 +68,7 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
*/ */
void omap_pm_idle(void) void omap_pm_idle(void)
{ {
int (*func_ptr)(void) = 0; int (*func_ptr)(void) = NULL;
unsigned int mask32 = 0; unsigned int mask32 = 0;
/* /*
...@@ -84,10 +89,19 @@ void omap_pm_idle(void) ...@@ -84,10 +89,19 @@ void omap_pm_idle(void)
local_irq_enable(); local_irq_enable();
#if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ) #if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ)
/* Override timer to use VST for the next cycle */ /* Override timer to use dynamic tick for the next cycle */
omap_32k_timer_next_vst_interrupt(); if ((system_timer->dyn_tick->state & DYN_TICK_ENABLED)
&& system_timer->dyn_tick->reprogram)
system_timer->dyn_tick->reprogram();
#endif #endif
/*
* Prevent the ULPD from entering low power state by setting
* POWER_CTRL_REG:4 = 0
*/
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
if ((mask32 & DSP_IDLE) == 0) { if ((mask32 & DSP_IDLE) == 0) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
} else { } else {
...@@ -111,58 +125,55 @@ void omap_pm_idle(void) ...@@ -111,58 +125,55 @@ void omap_pm_idle(void)
*/ */
static void omap_pm_wakeup_setup(void) static void omap_pm_wakeup_setup(void)
{ {
/* u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
* Enable ARM XOR clock and release peripheral from reset by u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
* writing 1 to PER_EN bit in ARM_RSTCT2, this is required
* for UART configuration to use UART2 to wake up.
*/
omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
/* /*
* Turn off all interrupts except L1-2nd level cascade, * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
* and the L2 wakeup interrupts: keypad and UART2. * and the L2 wakeup interrupts: keypad and UART2. Note that the
* drivers must still separately call omap_set_gpio_wakeup() to
* wake up to a GPIO interrupt.
*/ */
if (cpu_is_omap1510() || cpu_is_omap16xx())
level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
else if (cpu_is_omap730())
level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR); omap_writel(~level1_wake, OMAP_IH1_MIR);
if (cpu_is_omap1510()) { if (cpu_is_omap1510())
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR); omap_writel(~level2_wake, OMAP_IH2_MIR);
}
/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
if (cpu_is_omap16xx()) { if (cpu_is_omap16xx()) {
omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR); omap_writel(~level2_wake, OMAP_IH2_0_MIR);
omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
omap_writel(~0x0, OMAP_IH2_1_MIR);
omap_writel(~0x0, OMAP_IH2_2_MIR); omap_writel(~0x0, OMAP_IH2_2_MIR);
omap_writel(~0x0, OMAP_IH2_3_MIR); omap_writel(~0x0, OMAP_IH2_3_MIR);
} }
/* New IRQ agreement */ /* New IRQ agreement, recalculate in cascade order */
omap_writel(1, OMAP_IH2_CONTROL);
omap_writel(1, OMAP_IH1_CONTROL); omap_writel(1, OMAP_IH1_CONTROL);
/* external PULL to down, bit 22 = 0 */
omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
} }
void omap_pm_suspend(void) void omap_pm_suspend(void)
{ {
unsigned int mask32 = 0;
unsigned long arg0 = 0, arg1 = 0; unsigned long arg0 = 0, arg1 = 0;
int (*func_ptr)(unsigned short, unsigned short) = 0; int (*func_ptr)(unsigned short, unsigned short) = NULL;
unsigned short save_dsp_idlect2; unsigned short save_dsp_idlect2;
printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev); printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
if (machine_is_omap_osk()) { if (machine_is_omap_osk()) {
/* Stop LED1 (D9) blink */ /* Stop LED1 (D9) blink */
tps65010_set_led(LED1, OFF); tps65010_set_led(LED1, OFF);
} }
omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
/* /*
* Step 1: turn off interrupts * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
*/ */
local_irq_disable(); local_irq_disable();
...@@ -203,6 +214,8 @@ void omap_pm_suspend(void) ...@@ -203,6 +214,8 @@ void omap_pm_suspend(void)
ARM_SAVE(ARM_CKCTL); ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1); ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2); ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT); ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1); ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2); ARM_SAVE(ARM_RSTCT2);
...@@ -210,23 +223,7 @@ void omap_pm_suspend(void) ...@@ -210,23 +223,7 @@ void omap_pm_suspend(void)
ULPD_SAVE(ULPD_CLOCK_CTRL); ULPD_SAVE(ULPD_CLOCK_CTRL);
ULPD_SAVE(ULPD_STATUS_REQ); ULPD_SAVE(ULPD_STATUS_REQ);
/* /* (Step 3 removed - we now allow deep sleep by default) */
* Step 3: LOW_PWR signal enabling
*
* Allow the LOW_PWR signal to be visible on MPUIO5 ball.
*/
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
omap_writew(omap_readw(ULPD_POWER_CTRL) |
OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
/* /*
* Step 4: OMAP DSP Shutdown * Step 4: OMAP DSP Shutdown
...@@ -254,24 +251,9 @@ void omap_pm_suspend(void) ...@@ -254,24 +251,9 @@ void omap_pm_suspend(void)
omap_pm_wakeup_setup(); omap_pm_wakeup_setup();
/* /*
* Step 6a: ARM and Traffic controller shutdown * Step 6: ARM and Traffic controller shutdown
*
* Step 6 starts here with clock and watchdog disable
*/ */
/* stop clocks */
mask32 = omap_readl(ARM_IDLECT2);
mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
omap_writel(mask32, ARM_IDLECT2);
/* disable ARM watchdog */ /* disable ARM watchdog */
omap_writel(0x00F5, OMAP_WDT_TIMER_MODE); omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
omap_writel(0x00A0, OMAP_WDT_TIMER_MODE); omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
...@@ -312,17 +294,6 @@ void omap_pm_suspend(void) ...@@ -312,17 +294,6 @@ void omap_pm_suspend(void)
* If we are here, processor is woken up! * If we are here, processor is woken up!
*/ */
if (cpu_is_omap1510()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
} else if (cpu_is_omap16xx()) {
/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
omap_writew(omap_readw(ULPD_POWER_CTRL) &
~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
}
/* Restore DSP clocks */ /* Restore DSP clocks */
omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2); omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
__raw_writew(save_dsp_idlect2, DSP_IDLECT2); __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
...@@ -332,6 +303,8 @@ void omap_pm_suspend(void) ...@@ -332,6 +303,8 @@ void omap_pm_suspend(void)
* Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
*/ */
if (!(cpu_is_omap1510()))
ARM_RESTORE(ARM_IDLECT3);
ARM_RESTORE(ARM_CKCTL); ARM_RESTORE(ARM_CKCTL);
ARM_RESTORE(ARM_EWUPCT); ARM_RESTORE(ARM_EWUPCT);
ARM_RESTORE(ARM_RSTCT1); ARM_RESTORE(ARM_RSTCT1);
...@@ -362,6 +335,8 @@ void omap_pm_suspend(void) ...@@ -362,6 +335,8 @@ void omap_pm_suspend(void)
MPUI1610_RESTORE(OMAP_IH2_3_MIR); MPUI1610_RESTORE(OMAP_IH2_3_MIR);
} }
omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
/* /*
* Reenable interrupts * Reenable interrupts
*/ */
...@@ -397,6 +372,8 @@ static int omap_pm_read_proc( ...@@ -397,6 +372,8 @@ static int omap_pm_read_proc(
ARM_SAVE(ARM_CKCTL); ARM_SAVE(ARM_CKCTL);
ARM_SAVE(ARM_IDLECT1); ARM_SAVE(ARM_IDLECT1);
ARM_SAVE(ARM_IDLECT2); ARM_SAVE(ARM_IDLECT2);
if (!(cpu_is_omap1510()))
ARM_SAVE(ARM_IDLECT3);
ARM_SAVE(ARM_EWUPCT); ARM_SAVE(ARM_EWUPCT);
ARM_SAVE(ARM_RSTCT1); ARM_SAVE(ARM_RSTCT1);
ARM_SAVE(ARM_RSTCT2); ARM_SAVE(ARM_RSTCT2);
...@@ -432,6 +409,7 @@ static int omap_pm_read_proc( ...@@ -432,6 +409,7 @@ static int omap_pm_read_proc(
"ARM_CKCTL_REG: 0x%-8x \n" "ARM_CKCTL_REG: 0x%-8x \n"
"ARM_IDLECT1_REG: 0x%-8x \n" "ARM_IDLECT1_REG: 0x%-8x \n"
"ARM_IDLECT2_REG: 0x%-8x \n" "ARM_IDLECT2_REG: 0x%-8x \n"
"ARM_IDLECT3_REG: 0x%-8x \n"
"ARM_EWUPCT_REG: 0x%-8x \n" "ARM_EWUPCT_REG: 0x%-8x \n"
"ARM_RSTCT1_REG: 0x%-8x \n" "ARM_RSTCT1_REG: 0x%-8x \n"
"ARM_RSTCT2_REG: 0x%-8x \n" "ARM_RSTCT2_REG: 0x%-8x \n"
...@@ -445,6 +423,7 @@ static int omap_pm_read_proc( ...@@ -445,6 +423,7 @@ static int omap_pm_read_proc(
ARM_SHOW(ARM_CKCTL), ARM_SHOW(ARM_CKCTL),
ARM_SHOW(ARM_IDLECT1), ARM_SHOW(ARM_IDLECT1),
ARM_SHOW(ARM_IDLECT2), ARM_SHOW(ARM_IDLECT2),
ARM_SHOW(ARM_IDLECT3),
ARM_SHOW(ARM_EWUPCT), ARM_SHOW(ARM_EWUPCT),
ARM_SHOW(ARM_RSTCT1), ARM_SHOW(ARM_RSTCT1),
ARM_SHOW(ARM_RSTCT2), ARM_SHOW(ARM_RSTCT2),
...@@ -503,7 +482,7 @@ static void omap_pm_init_proc(void) ...@@ -503,7 +482,7 @@ static void omap_pm_init_proc(void)
entry = create_proc_read_entry("driver/omap_pm", entry = create_proc_read_entry("driver/omap_pm",
S_IWUSR | S_IRUGO, NULL, S_IWUSR | S_IRUGO, NULL,
omap_pm_read_proc, 0); omap_pm_read_proc, NULL);
} }
#endif /* DEBUG && CONFIG_PROC_FS */ #endif /* DEBUG && CONFIG_PROC_FS */
...@@ -576,7 +555,21 @@ static int omap_pm_finish(suspend_state_t state) ...@@ -576,7 +555,21 @@ static int omap_pm_finish(suspend_state_t state)
} }
struct pm_ops omap_pm_ops ={ static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
struct pt_regs * regs)
{
return IRQ_HANDLED;
}
static struct irqaction omap_wakeup_irq = {
.name = "peripheral wakeup",
.flags = SA_INTERRUPT,
.handler = omap_wakeup_interrupt
};
static struct pm_ops omap_pm_ops ={
.pm_disk_mode = 0, .pm_disk_mode = 0,
.prepare = omap_pm_prepare, .prepare = omap_pm_prepare,
.enter = omap_pm_enter, .enter = omap_pm_enter,
...@@ -602,7 +595,7 @@ static int __init omap_pm_init(void) ...@@ -602,7 +595,7 @@ static int __init omap_pm_init(void)
omap1510_cpu_suspend_sz); omap1510_cpu_suspend_sz);
} else } else
#endif #endif
if (cpu_is_omap1610() || cpu_is_omap1710()) { if (cpu_is_omap16xx()) {
memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND, memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
omap1610_idle_loop_suspend, omap1610_idle_loop_suspend,
omap1610_idle_loop_suspend_sz); omap1610_idle_loop_suspend_sz);
...@@ -616,12 +609,37 @@ static int __init omap_pm_init(void) ...@@ -616,12 +609,37 @@ static int __init omap_pm_init(void)
omap1610_cpu_suspend_sz); omap1610_cpu_suspend_sz);
} }
setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
#if 0
/* --- BEGIN BOARD-DEPENDENT CODE --- */
/* Sleepx mask direction */
omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
/* Unmask sleepx signal */
omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
/* --- END BOARD-DEPENDENT CODE --- */
#endif
/* Program new power ramp-up time
* (0 for most boards since we don't lower voltage when in deep sleep)
*/
omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
/* Configure IDLECT3 */
if (cpu_is_omap16xx())
omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
pm_set_ops(&omap_pm_ops); pm_set_ops(&omap_pm_ops);
#if defined(DEBUG) && defined(CONFIG_PROC_FS) #if defined(DEBUG) && defined(CONFIG_PROC_FS)
omap_pm_init_proc(); omap_pm_init_proc();
#endif #endif
/* configure LOW_PWR pin */
omap_cfg_reg(T20_1610_LOW_PWR);
return 0; return 0;
} }
__initcall(omap_pm_init); __initcall(omap_pm_init);
......
...@@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend) ...@@ -66,7 +66,7 @@ ENTRY(omap1510_idle_loop_suspend)
@ get ARM_IDLECT2 into r2 @ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle @ request ARM idle
...@@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend) ...@@ -76,7 +76,7 @@ ENTRY(omap1510_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510: subs r5, r5, #1 l_1510: subs r5, r5, #1
bne l_1510 bne l_1510
/* /*
...@@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1 ...@@ -96,7 +96,7 @@ l_1510: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1510_idle_loop_suspend_sz) ENTRY(omap1510_idle_loop_suspend_sz)
.word . - omap1510_idle_loop_suspend .word . - omap1510_idle_loop_suspend
...@@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend) ...@@ -115,8 +115,8 @@ ENTRY(omap1610_idle_loop_suspend)
@ turn off clock domains @ turn off clock domains
@ get ARM_IDLECT2 into r2 @ get ARM_IDLECT2 into r2
ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00 orr r5,r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle @ request ARM idle
...@@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend) ...@@ -126,7 +126,7 @@ ENTRY(omap1610_idle_loop_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1610: subs r5, r5, #1 l_1610: subs r5, r5, #1
bne l_1610 bne l_1610
/* /*
...@@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1 ...@@ -146,7 +146,7 @@ l_1610: subs r5, r5, #1
strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
ldmfd sp!, {r0 - r12, pc} @ restore regs and return ldmfd sp!, {r0 - r12, pc} @ restore regs and return
ENTRY(omap1610_idle_loop_suspend_sz) ENTRY(omap1610_idle_loop_suspend_sz)
.word . - omap1610_idle_loop_suspend .word . - omap1610_idle_loop_suspend
...@@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend) ...@@ -208,7 +208,7 @@ ENTRY(omap1510_cpu_suspend)
@ turn off clock domains @ turn off clock domains
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle @ request ARM idle
...@@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend) ...@@ -217,7 +217,7 @@ ENTRY(omap1510_cpu_suspend)
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff mov r5, #IDLE_WAIT_CYCLES & 0xff
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
l_1510_2: l_1510_2:
subs r5, r5, #1 subs r5, r5, #1
bne l_1510_2 bne l_1510_2
...@@ -237,7 +237,7 @@ l_1510_2: ...@@ -237,7 +237,7 @@ l_1510_2:
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ restore regs and return @ restore regs and return
ldmfd sp!, {r0 - r12, pc} ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1510_cpu_suspend_sz) ENTRY(omap1510_cpu_suspend_sz)
.word . - omap1510_cpu_suspend .word . - omap1510_cpu_suspend
...@@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend) ...@@ -249,21 +249,26 @@ ENTRY(omap1610_cpu_suspend)
@ save registers on stack @ save registers on stack
stmfd sp!, {r0 - r12, lr} stmfd sp!, {r0 - r12, lr}
@ Drain write cache
mov r4, #0
mcr p15, 0, r0, c7, c10, 4
nop
@ load base address of Traffic Controller @ load base address of Traffic Controller
mov r4, #TCMIF_ASM_BASE & 0xff000000 mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
@ prepare to put SDRAM into self-refresh manually @ prepare to put SDRAM into self-refresh manually
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
@ prepare to put EMIFS to Sleep @ prepare to put EMIFS to Sleep
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ load base address of ARM_IDLECT1 and ARM_IDLECT2 @ load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
...@@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend) ...@@ -271,26 +276,22 @@ ENTRY(omap1610_cpu_suspend)
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
@ turn off clock domains @ turn off clock domains
mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff @ do not disable PERCK (0x04)
orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00 mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] orr r5,r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
@ work around errata of OMAP1610/5912. Enable (!) peripheral
@ clock to let the chip go into deep sleep
ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
orr r5,r5, #EN_PERCK_BIT & 0xff
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
@ request ARM idle @ request ARM idle
mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00 orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
mov r5, #IDLE_WAIT_CYCLES & 0xff @ disable instruction cache
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 mrc p15, 0, r9, c1, c0, 0
l_1610_2: bic r2, r9, #0x1000
subs r5, r5, #1 mcr p15, 0, r2, c1, c0, 0
bne l_1610_2 nop
/* /*
* Let's wait for the next wake up event to wake us up. r0 can't be * Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1 * used here because r0 holds ARM_IDLECT1
...@@ -301,11 +302,19 @@ l_1610_2: ...@@ -301,11 +302,19 @@ l_1610_2:
* omap1610_cpu_suspend()'s resume point. * omap1610_cpu_suspend()'s resume point.
* *
* It will just start executing here, so we'll restore stuff from the * It will just start executing here, so we'll restore stuff from the
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2. * stack.
*/ */
@ re-enable Icache
mcr p15, 0, r9, c1, c0, 0
@ reset the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@ Restore EMIFF controls
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
@ restore regs and return @ restore regs and return
ldmfd sp!, {r0 - r12, pc} ldmfd sp!, {r0 - r12, pc}
......
...@@ -61,7 +61,10 @@ ...@@ -61,7 +61,10 @@
#define PER_EN 0x1 #define PER_EN 0x1
#define CPU_SUSPEND_SIZE 200 #define CPU_SUSPEND_SIZE 200
#define ULPD_LOW_POWER_EN 0x0001 #define ULPD_LOW_PWR_EN 0x0001
#define ULPD_DEEP_SLEEP_TRANSITION_EN 0x0010
#define ULPD_SETUP_ANALOG_CELL_3_VAL 0
#define ULPD_POWER_CTRL_REG_VAL 0x0219
#define DSP_IDLE_DELAY 10 #define DSP_IDLE_DELAY 10
#define DSP_IDLE 0x0040 #define DSP_IDLE 0x0040
...@@ -86,13 +89,14 @@ ...@@ -86,13 +89,14 @@
#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5 #define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5
#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00 #define OMAP1510_IDLE_LOOP_REQUEST 0x0c00
#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2 #define OMAP1510_IDLE_CLOCK_DOMAINS 0x2
#define OMAP1510_ULPD_LOW_POWER_REQ 0x0001
#define OMAP1610_DEEP_SLEEP_REQUEST 0x17c7 /* Both big sleep and deep sleep use same values. Difference is in ULPD. */
#define OMAP1610_BIG_SLEEP_REQUEST TBD #define OMAP1610_IDLECT1_SLEEP_VAL 0x13c7
#define OMAP1610_IDLECT2_SLEEP_VAL 0x09c7
#define OMAP1610_IDLECT3_VAL 0x3f
#define OMAP1610_IDLECT3_SLEEP_ORMASK 0x2c
#define OMAP1610_IDLECT3 0xfffece24
#define OMAP1610_IDLE_LOOP_REQUEST 0x0400 #define OMAP1610_IDLE_LOOP_REQUEST 0x0400
#define OMAP1610_IDLE_CLOCK_DOMAINS 0x09c7
#define OMAP1610_ULPD_LOW_POWER_REQ 0x3
#ifndef OMAP1510_SRAM_IDLE_SUSPEND #ifndef OMAP1510_SRAM_IDLE_SUSPEND
#define OMAP1510_SRAM_IDLE_SUSPEND 0 #define OMAP1510_SRAM_IDLE_SUSPEND 0
...@@ -161,6 +165,7 @@ enum arm_save_state { ...@@ -161,6 +165,7 @@ enum arm_save_state {
ARM_SLEEP_SAVE_ARM_CKCTL, ARM_SLEEP_SAVE_ARM_CKCTL,
ARM_SLEEP_SAVE_ARM_IDLECT1, ARM_SLEEP_SAVE_ARM_IDLECT1,
ARM_SLEEP_SAVE_ARM_IDLECT2, ARM_SLEEP_SAVE_ARM_IDLECT2,
ARM_SLEEP_SAVE_ARM_IDLECT3,
ARM_SLEEP_SAVE_ARM_EWUPCT, ARM_SLEEP_SAVE_ARM_EWUPCT,
ARM_SLEEP_SAVE_ARM_RSTCT1, ARM_SLEEP_SAVE_ARM_RSTCT1,
ARM_SLEEP_SAVE_ARM_RSTCT2, ARM_SLEEP_SAVE_ARM_RSTCT2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment