From 92105bb70634abacc08bbe12bf6f888fbd7dad38 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 7 Sep 2005 17:20:26 +0100 Subject: [ARM] 2887/1: OMAP 2/4: Update files common to omap1 and omap2, take 2 Patch from Tony Lindgren This patch syncs the mainline kernel with linux-omap tree. The highlights of the patch are: - Clock updates by Tuukka Tikkanen, Juha Yrjola, Daniel Petrini and Tony Lindgren - DMA fixes by Imre Deak, Juha Yrjola and Daniel Petrini - Add support to dual-mode hardware timers by Lauri Leukkunen - GPIO support for 24xx by Paul Mundt - GPIO wake-up support by Tony Lindgren - Better GPIO interrupt handler to not lose interrupts by Ralph Walden and Ladislav Michl - Power Management updates by Tuukka Tikkanen - Make Power Management code use new SRAM functions by Tony Lindgren Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/plat-omap/pm.c | 255 ++++++++++++++++++++++-------------------------- 1 file changed, 116 insertions(+), 139 deletions(-) (limited to 'arch/arm/plat-omap/pm.c') diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index e6536b16c38..e15c6c1ddec 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c @@ -39,24 +39,32 @@ #include #include #include +#include #include +#include #include -#include +#include -#include +#include +#include +#include #include #include -#include #include +#include #include "clock.h" +#include "sram.h" static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; +static void (*omap_sram_idle)(void) = NULL; +static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL; + /* * Let's power down on idle, but only if we are really * idle, because once we start down the path of @@ -65,7 +73,6 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; */ void omap_pm_idle(void) { - int (*func_ptr)(void) = 0; unsigned int mask32 = 0; /* @@ -83,6 +90,13 @@ void omap_pm_idle(void) } mask32 = omap_readl(ARM_SYSST); + /* + * 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); + /* * Since an interrupt may set up a timer, we don't want to * reprogram the hardware timer with interrupts enabled. @@ -92,18 +106,9 @@ void omap_pm_idle(void) if ((mask32 & DSP_IDLE) == 0) { __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); - } else { - - if (cpu_is_omap1510()) { - func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND); - } else if (cpu_is_omap1610() || cpu_is_omap1710()) { - func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND); - } else if (cpu_is_omap5912()) { - func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND); - } + } else + omap_sram_idle(); - func_ptr(); - } local_fiq_enable(); local_irq_enable(); } @@ -115,58 +120,55 @@ void omap_pm_idle(void) */ static void omap_pm_wakeup_setup(void) { - /* - * Enable ARM XOR clock and release peripheral from reset by - * 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); + u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ); + u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD); /* - * Turn off all interrupts except L1-2nd level cascade, - * and the L2 wakeup interrupts: keypad and UART2. + * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade, + * 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()) { - omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR); - } + if (cpu_is_omap1510()) + omap_writel(~level2_wake, OMAP_IH2_MIR); + /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */ if (cpu_is_omap16xx()) { - omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR); - - omap_writel(~0x0, OMAP_IH2_1_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_2_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); - - /* 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) { - unsigned int mask32 = 0; unsigned long arg0 = 0, arg1 = 0; - int (*func_ptr)(unsigned short, unsigned short) = 0; - 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); + + omap_serial_wake_trigger(1); if (machine_is_omap_osk()) { /* Stop LED1 (D9) blink */ 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(); @@ -207,6 +209,8 @@ void omap_pm_suspend(void) ARM_SAVE(ARM_CKCTL); ARM_SAVE(ARM_IDLECT1); ARM_SAVE(ARM_IDLECT2); + if (!(cpu_is_omap1510())) + ARM_SAVE(ARM_IDLECT3); ARM_SAVE(ARM_EWUPCT); ARM_SAVE(ARM_RSTCT1); ARM_SAVE(ARM_RSTCT2); @@ -214,42 +218,12 @@ void omap_pm_suspend(void) ULPD_SAVE(ULPD_CLOCK_CTRL); ULPD_SAVE(ULPD_STATUS_REQ); - /* - * 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 3 removed - we now allow deep sleep by default) */ /* * Step 4: OMAP DSP Shutdown */ - /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */ - omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE, - ARM_RSTCT1); - - /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */ - omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG); - - /* Set EN_DSPCK = 0, stop DSP block clock */ - omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL); - - /* Stop any DSP domain clocks */ - omap_writel(omap_readl(ARM_IDLECT2) | (1< 0 (WDT clock) */ - mask32 |= (1< 1 (XORPCK clock) */ - mask32 &= ~(1< 0 (MPUPER_CK clock) */ - mask32 &= ~(1< 0 (LCDC clock) */ - mask32 &= ~(1< 0 (local bus clock) */ - mask32 |= (1< 1 (MPUI clock) */ - mask32 &= ~(1< 0 (MPU timer clock) */ - mask32 &= ~(1< 0 (DMAC clock) */ - mask32 &= ~(1< 0 (GPIO clock) */ - omap_writel(mask32, ARM_IDLECT2); - /* disable ARM watchdog */ omap_writel(0x00F5, OMAP_WDT_TIMER_MODE); omap_writel(0x00A0, OMAP_WDT_TIMER_MODE); @@ -295,47 +254,24 @@ void omap_pm_suspend(void) arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1]; arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2]; - if (cpu_is_omap1510()) { - func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND); - } else if (cpu_is_omap1610() || cpu_is_omap1710()) { - func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND); - } else if (cpu_is_omap5912()) { - func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND); - } - /* * Step 6c: ARM and Traffic controller shutdown * * Jump to assembly code. The processor will stay there * until wake up. */ - - func_ptr(arg0, arg1); + omap_sram_suspend(arg0, arg1); /* * 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 */ - omap_writel(omap_readl(ARM_IDLECT2) | (1<