]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: Add minimal PM support for omap2
authorTony Lindgren <tony@atomide.com>
Thu, 12 Jan 2006 20:32:31 +0000 (12:32 -0800)
committerTony Lindgren <tony@atomide.com>
Thu, 12 Jan 2006 20:32:31 +0000 (12:32 -0800)
This patch adds minimal pm.c and sleep.S for omap2.

Please note that it does not contain suspend or voltage scaling yet.

arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/pm.c [new file with mode: 0644]
arch/arm/mach-omap2/prcm-regs.h
arch/arm/mach-omap2/sleep.S [new file with mode: 0644]
include/asm-arm/arch-omap/pm.h

index 4cc80f77fc9d7c6140ce0ee5f367d6301f4ae249..314d0aae5fe6c5013f98844fdd60ed2b823569bb 100644 (file)
@@ -7,6 +7,9 @@ obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o seria
 
 obj-$(CONFIG_OMAP_MPU_TIMER)           += timer-gp.o
 
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)                += board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)             += board-h4.o
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644 (file)
index 0000000..562168f
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+       local_irq_disable();
+       local_fiq_disable();
+       if (need_resched()) {
+               local_fiq_enable();
+               local_irq_enable();
+               return;
+       }
+
+       /*
+        * Since an interrupt may set up a timer, we don't want to
+        * reprogram the hardware timer with interrupts enabled.
+        * Re-enable interrupts only after returning from idle.
+        */
+       timer_dyn_reprogram();
+
+       omap2_sram_idle();
+       local_fiq_enable();
+       local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+       int error = 0;
+
+       /* We cannot sleep in idle until we have resumed */
+       saved_idle = pm_idle;
+       pm_idle = NULL;
+
+       switch (state)
+       {
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               break;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+
+       default:
+               return -EINVAL;
+       }
+
+       return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+       switch (state)
+       {
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               /* FIXME: Add suspend */
+               break;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+       pm_idle = saved_idle;
+       return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+       .pm_disk_mode   = 0,
+       .prepare        = omap2_pm_prepare,
+       .enter          = omap2_pm_enter,
+       .finish         = omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+       printk("Power Management for TI OMAP.\n");
+
+       vclk = clk_get(NULL, "virt_prcm_set");
+       if (IS_ERR(vclk)) {
+               printk(KERN_ERR "Could not get PM vclk\n");
+               return -ENODEV;
+       }
+
+       /*
+        * We copy the assembler sleep/wakeup routines to SRAM.
+        * These routines need to be in SRAM as that's the only
+        * memory the MPU can see when it wakes up.
+        */
+       omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+                                        omap24xx_idle_loop_suspend_sz);
+
+       omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+                                           omap24xx_cpu_suspend_sz);
+
+       pm_set_ops(&omap_pm_ops);
+       pm_idle = omap2_pm_idle;
+
+       return 0;
+}
+
+__initcall(omap2_pm_init);
index 72337cab03b65fc9086719bf839efde27acb347f..4119b50ecac79ee9f1119543247c085aa9951da7 100644 (file)
 #define CM_FCLKEN_MDM          PRCM_REG32(0xC00)
 #define CM_ICLKEN_MDM          PRCM_REG32(0xC10)
 #define CM_IDLEST_MDM          PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM                PRCM_REG32(0xC30)
 #define CM_CLKSEL_MDM          PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE              (OMAP24XX_L4_IO_BASE+0x50000)
+#define CM_CLKSTCTRL_MDM       PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM         PRCM_REG32(0xC50)
+#define RM_RSTST_MDM           PRCM_REG32(0xC58)
+#define PM_WKEN_MDM            PRCM_REG32(0xCA0)
+#define PM_WKST_MDM            PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM           PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM                PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM          PRCM_REG32(0xCE4)
+
+#define OMAP24XX_L4_IO_BASE    0x48000000
+
+#define DISP_BASE              (OMAP24XX_L4_IO_BASE + 0x50000)
 #define DISP_REG32(offset)     __REG32(DISP_BASE + (offset))
 
 #define OMAP24XX_GPMC_BASE     (L3_24XX_BASE + 0xa000)
-#define GPMC_BASE              (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset)     __REG32(GPMC_BASE + (offset))
+#define GPMC_REG32(offset)     __REG32(OMAP24XX_GPMC_BASE + (offset))
 
-#define GPT1_BASE              (OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE              (0x48028000)
 #define GPT1_REG32(offset)     __REG32(GPT1_BASE + (offset))
 
 /* Misc sysconfig */
 #define DISPC_SYSCONFIG                DISP_REG32(0x410)
-#define SPI_BASE               (OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE               (OMAP24XX_L4_IO_BASE + 0x98000)
 #define MCSPI1_SYSCONFIG       __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG       __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG    0x5A000010
-#define CAMERA_MMU_SYSCONFIG   __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG    0x5D000010
-//#define DSP_DMA_SYSCONFIG    0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG   __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG   __REG32(DISP_BASE+0x602C)
+#define MCSPI2_SYSCONFIG       __REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG       __REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+
+#define CAMERA_MMU_SYSCONFIG   __REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG   __REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG   __REG32(DISP_BASE + 0x602C)
 #define GPMC_SYSCONFIG         GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG    __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG                0x5C060010
-#define SDRC_SYSCONFIG         __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG          __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG          __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG      0x67FFFE10
+#define MAILBOXES_SYSCONFIG    __REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG         __REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE      (L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG          __REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG          __REG32(DISP_BASE + 0x8010)
 
 /* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2          (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3          (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4          (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5          (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6          (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7          (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8          (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9          (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10         (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11         (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12         (OMAP24XX_L4_IO_BASE+0x8A000)
-
+#define OMAP24XX_GPT2          (OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3          (OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4          (OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5          (OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6          (OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7          (OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8          (OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9          (OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10         (OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11         (OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12         (OMAP24XX_L4_IO_BASE + 0x8A000)
+
+/* FIXME: Move these to timer code */
 #define GPTIMER1_SYSCONFIG     GPT1_REG32(0x010)
 #define GPTIMER2_SYSCONFIG     __REG32(OMAP24XX_GPT2 + 0x10)
 #define GPTIMER3_SYSCONFIG     __REG32(OMAP24XX_GPT3 + 0x10)
 #define GPTIMER11_SYSCONFIG    __REG32(OMAP24XX_GPT11 + 0x10)
 #define GPTIMER12_SYSCONFIG    __REG32(OMAP24XX_GPT12 + 0x10)
 
-#define GPIOX_BASE(X)          (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE     0x48018000
+#define GPIOX_BASE(X)          (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
 
-#define GPIO1_SYSCONFIG                __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG                __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG                __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG                __REG32((GPIOX_BASE(4)+0x10))
+#define GPIO1_SYSCONFIG                __REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG                __REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG                __REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG                __REG32((GPIOX_BASE(4) + 0x10))
+
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG                __REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
 
 /* GP TIMER 1 */
 #define GPTIMER1_TISTAT                GPT1_REG32(0x014)
 #define GPTIMER1_TCAR2         GPT1_REG32(0x044)
 
 /* rkw -- base fix up please... */
-#define GPTIMER3_TISR          __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR          __REG32(OMAP24XX_L4_IO_BASE + 0x78018)
 
 /* SDRC */
-#define SDRC_DLLA_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER             __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0              __REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL         __REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS       __REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL         __REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS       __REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER             __REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0              __REG32(OMAP24XX_SDRC_BASE + 0x084)
 
 /* GPIO 1 */
 #define GPIO1_BASE             GPIOX_BASE(1)
 #define GPIO2_DATAIN           GPIO2_REG32(0x038)
 #define GPIO2_OE               GPIO2_REG32(0x034)
 #define GPIO2_DATAOUT          GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE    GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME   GPIO2_REG32(0x054)
 
 /* GPIO 3 */
 #define GPIO3_BASE             GPIOX_BASE(3)
 #define GPIO3_DATAOUT          GPIO3_REG32(0x03C)
 #define GPIO3_DEBOUNCENABLE    GPIO3_REG32(0x050)
 #define GPIO3_DEBOUNCINGTIME   GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE    GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME   GPIO3_REG32(0x054)
 
 /* GPIO 4 */
 #define GPIO4_BASE             GPIOX_BASE(4)
 #define GPIO4_DEBOUNCENABLE    GPIO4_REG32(0x050)
 #define GPIO4_DEBOUNCINGTIME   GPIO4_REG32(0x054)
 
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset)    __REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1       GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1       GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2       GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2       GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE     GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT     GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT    GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN           GPIO5_REG32(0x038)
+#define GPIO5_OE               GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT          GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE    GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME   GPIO5_REG32(0x054)
+#endif
 
 /* IO CONFIG */
-#define CONTROL_BASE           (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset)  __REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE             (L4_24XX_BASE)
+#define CONTROL_REG32(offset)          __REG32(OMAP24XX_CTRL_BASE + (offset))
 
 #define CONTROL_PADCONF_SPI1_NCS2      CONTROL_REG32(0x104)
 #define CONTROL_PADCONF_SYS_XTALOUT    CONTROL_REG32(0x134)
 #define CONTROL_PADCONF_MCBSP1_DX      CONTROL_REG32(0x10C)
 #define CONTROL_PADCONF_GPMC_NCS4      CONTROL_REG32(0x090)
 #define CONTROL_PADCONF_DSS_D5         CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9         CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9         CONTROL_REG32(0x0BC)    /* 2420 */
 #define CONTROL_PADCONF_DSS_D13                CONTROL_REG32(0x0C0)
 #define CONTROL_PADCONF_DSS_VSYNC      CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0     CONTROL_REG32(0x0BC)    /* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX   CONTROL_REG32(0x108)    /* 2430 */
 
 /* CONTROL */
 #define CONTROL_DEVCONF                CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1       CONTROL_REG32(0x2E8)
 
 /* INTERRUPT CONTROLLER */
-#define INTC_BASE              (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE              ((L4_24XX_BASE) + 0xfe000)
 #define INTC_REG32(offset)     __REG32(INTC_BASE + (offset))
 
 #define INTC1_U_BASE           INTC_REG32(0x000)
 #define INTC_ISR_CLEAR2                INTC_REG32(0x0D4)
 #define INTC_SIR_IRQ           INTC_REG32(0x040)
 #define INTC_CONTROL           INTC_REG32(0x048)
-#define INTC_ILR11             INTC_REG32(0x12C)
+#define INTC_ILR11             INTC_REG32(0x12C)       /* PRCM on MPU PIC */
+#define INTC_ILR30             INTC_REG32(0x178)
+#define INTC_ILR31             INTC_REG32(0x17C)
 #define INTC_ILR32             INTC_REG32(0x180)
-#define INTC_ILR37             INTC_REG32(0x194)
-#define INTC_SYSCONFIG         INTC_REG32(0x010)
+#define INTC_ILR37             INTC_REG32(0x194)       /* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG         INTC_REG32(0x010)       /* GPT1 on MPU PIC */
 
 /* RAM FIREWALL */
 #define RAMFW_BASE             (0x68005000)
 #define DISPC_DATA_CYCLE2      DISP_REG32(0x5D8)
 #define DISPC_DATA_CYCLE3      DISP_REG32(0x5DC)
 
-/* Wake up define for board */
-#define GPIO97                 (1 << 1)
-#define GPIO88                 (1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL             __REG8(0x480AC001)
+#define USBOTG_POWER           __REG32(0x480AC000)
+
+/* HS MMC */
+#define MMCHS1_SYSCONFIG       __REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG       __REG32(0x480b4010)
 
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLER__ */
 
 #endif
 
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644 (file)
index 0000000..00299cb
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V         IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V      IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V   IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V       IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V    IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V     IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V     IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V     IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define        A_SDRC_POWER_V          IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V      IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V              (0xC0000000)
+#define A_SDRC_MANUAL_V                IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+       .text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_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(omap24xx_idle_loop_suspend)
+       stmfd   sp!, {r0, lr}           @ save registers on stack
+       mov     r0, #0                  @ clear for mcr setup
+       mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
+       ldmfd   sp!, {r0, pc}           @ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+       .word   . - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 :        DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ *     2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ *     2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't.  We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL.  Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+       stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
+       mov     r3, #0x0                @ clear for mrc call
+       mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
+       nop
+       nop
+       ldr     r3, A_SDRC_POWER        @ addr of sdrc power
+       ldr     r4, [r3]                @ value of sdrc power
+       orr     r4, r4, #0x40           @ enable self refresh on idle req
+       mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
+       str     r4, [r3]                @ make it so
+       mov     r2, #0
+       nop
+       mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
+       nop
+loop:
+       subs    r5, r5, #0x1            @ awake, wait just a bit
+       bne     loop
+
+       /* The DPLL has on before we take the DDR out of self refresh */
+       bic     r4, r4, #0x40           @ now clear self refresh bit.
+       str     r4, [r3]                @ put vlaue back.
+       ldr     r4, A_SDRC0             @ make a clock happen
+       ldr     r4, [r4]
+       nop                             @ start auto refresh only after clk ok
+       movs    r0, r0                  @ see if DDR or SDR
+       ldrne   r1, A_SDRC_DLLA_CTRL_S  @ get addr of DLL ctrl
+       strne   r0, [r1]                @ rewrite DLLA to force DLL reload
+       addne   r1, r1, #0x8            @ move to DLLB
+       strne   r0, [r1]                @ rewrite DLLB to force DLL reload
+
+       mov     r5, #0x1000
+loop2:
+       subs    r5, r5, #0x1
+       bne     loop2
+       /* resume*/
+       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+
+A_SDRC_POWER:
+       .word A_SDRC_POWER_V
+A_SDRC0:
+       .word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+       .word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+       .word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+       .word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+       .word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+       .word   . - omap24xx_cpu_suspend
+
index 401aec93b8c72461c539d4cd94286c40d05d42a2..75960498259a0e3625addc7a5fc8bcbaf72b9a15 100644 (file)
@@ -49,7 +49,7 @@
 
 /*
  * ----------------------------------------------------------------------------
- * Powermanagement bitmasks
+ * Power management bitmasks
  * ----------------------------------------------------------------------------
  */
 #define IDLE_WAIT_CYCLES               0x00000fff
@@ -135,9 +135,20 @@ extern void omap_pm_suspend(void);
 extern void omap730_cpu_suspend(unsigned short, unsigned short);
 extern void omap1510_cpu_suspend(unsigned short, unsigned short);
 extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision);
 extern void omap730_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
+extern void omap24xx_idle_loop_suspend(void);
+
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+extern unsigned int omap24xx_idle_loop_suspend_sz;
 
 #ifdef CONFIG_OMAP_SERIAL_WAKE
 extern void omap_serial_wake_trigger(int enable);
@@ -146,13 +157,6 @@ extern void omap_serial_wake_trigger(int enable);
 #define omap_serial_wake_trigger(x)    {}
 #endif /* CONFIG_OMAP_SERIAL_WAKE */
 
-extern unsigned int omap730_cpu_suspend_sz;
-extern unsigned int omap730_idle_loop_suspend_sz;
-extern unsigned int omap1510_cpu_suspend_sz;
-extern unsigned int omap1510_idle_loop_suspend_sz;
-extern unsigned int omap1610_cpu_suspend_sz;
-extern unsigned int omap1610_idle_loop_suspend_sz;
-
 #define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
 #define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
 #define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
@@ -173,6 +177,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz;
 #define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
 #define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
 
+#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x
+#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+
 /*
  * List of global OMAP registers to preserve.
  * More ones like CP and general purpose register values are preserved
@@ -273,5 +281,30 @@ enum mpui1610_save_state {
 #endif
 };
 
+enum omap24xx_save_state {
+       OMAP24XX_SLEEP_SAVE_START = 0,
+       OMAP24XX_SLEEP_SAVE_INTC_MIR0,
+       OMAP24XX_SLEEP_SAVE_INTC_MIR1,
+       OMAP24XX_SLEEP_SAVE_INTC_MIR2,
+       OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE,
+       OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE,
+       OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE,
+       OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE,
+       OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE,
+       OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1,
+       OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,
+       OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1,
+       OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1,
+       OMAP24XX_SLEEP_SAVE_GPIO3_OE,
+       OMAP24XX_SLEEP_SAVE_GPIO4_OE,
+       OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT,
+       OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT,
+       OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2,
+       OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX,
+       OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX,
+       OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0,
+       OMAP24XX_SLEEP_SAVE_SIZE
+};
+
 #endif /* ASSEMBLER */
 #endif /* __ASM_ARCH_OMAP_PM_H */