summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/control.c381
-rw-r--r--arch/arm/mach-omap2/gpmc.c98
-rw-r--r--arch/arm/mach-omap2/irq.c66
-rw-r--r--arch/arm/mach-omap2/pm-debug.c29
-rw-r--r--arch/arm/mach-omap2/pm.h10
-rw-r--r--arch/arm/mach-omap2/pm34xx.c362
-rw-r--r--arch/arm/mach-omap2/powerdomains34xx.h8
-rw-r--r--arch/arm/mach-omap2/prcm.c407
-rw-r--r--arch/arm/mach-omap2/prm-regbits-34xx.h2
-rw-r--r--arch/arm/mach-omap2/sdrc.c27
-rw-r--r--arch/arm/mach-omap2/serial.c2
-rw-r--r--arch/arm/mach-omap2/sleep34xx.S218
-rw-r--r--arch/arm/mach-omap2/timer-gp.c2
13 files changed, 1570 insertions, 42 deletions
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 6adb360c6d45..cdd1f35636dd 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -17,9 +17,125 @@
#include <plat/common.h>
#include <plat/control.h>
+#include <plat/sdrc.h>
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+#include "cm.h"
+#include "prm.h"
+#include "sdrc.h"
static void __iomem *omap2_ctrl_base;
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+struct omap3_scratchpad {
+ u32 boot_config_ptr;
+ u32 public_restore_ptr;
+ u32 secure_ram_restore_ptr;
+ u32 sdrc_module_semaphore;
+ u32 prcm_block_offset;
+ u32 sdrc_block_offset;
+};
+
+struct omap3_scratchpad_prcm_block {
+ u32 prm_clksrc_ctrl;
+ u32 prm_clksel;
+ u32 cm_clksel_core;
+ u32 cm_clksel_wkup;
+ u32 cm_clken_pll;
+ u32 cm_autoidle_pll;
+ u32 cm_clksel1_pll;
+ u32 cm_clksel2_pll;
+ u32 cm_clksel3_pll;
+ u32 cm_clken_pll_mpu;
+ u32 cm_autoidle_pll_mpu;
+ u32 cm_clksel1_pll_mpu;
+ u32 cm_clksel2_pll_mpu;
+ u32 prcm_block_size;
+};
+
+struct omap3_scratchpad_sdrc_block {
+ u16 sysconfig;
+ u16 cs_cfg;
+ u16 sharing;
+ u16 err_type;
+ u32 dll_a_ctrl;
+ u32 dll_b_ctrl;
+ u32 power;
+ u32 cs_0;
+ u32 mcfg_0;
+ u16 mr_0;
+ u16 emr_1_0;
+ u16 emr_2_0;
+ u16 emr_3_0;
+ u32 actim_ctrla_0;
+ u32 actim_ctrlb_0;
+ u32 rfr_ctrl_0;
+ u32 cs_1;
+ u32 mcfg_1;
+ u16 mr_1;
+ u16 emr_1_1;
+ u16 emr_2_1;
+ u16 emr_3_1;
+ u32 actim_ctrla_1;
+ u32 actim_ctrlb_1;
+ u32 rfr_ctrl_1;
+ u16 dcdl_1_ctrl;
+ u16 dcdl_2_ctrl;
+ u32 flags;
+ u32 block_size;
+};
+
+void *omap3_secure_ram_storage;
+
+/*
+ * This is used to store ARM registers in SDRAM before attempting
+ * an MPU OFF. The save and restore happens from the SRAM sleep code.
+ * The address is stored in scratchpad, so that it can be used
+ * during the restore path.
+ */
+u32 omap3_arm_context[128];
+
+struct omap3_control_regs {
+ u32 sysconfig;
+ u32 devconf0;
+ u32 mem_dftrw0;
+ u32 mem_dftrw1;
+ u32 msuspendmux_0;
+ u32 msuspendmux_1;
+ u32 msuspendmux_2;
+ u32 msuspendmux_3;
+ u32 msuspendmux_4;
+ u32 msuspendmux_5;
+ u32 sec_ctrl;
+ u32 devconf1;
+ u32 csirxfe;
+ u32 iva2_bootaddr;
+ u32 iva2_bootmod;
+ u32 debobs_0;
+ u32 debobs_1;
+ u32 debobs_2;
+ u32 debobs_3;
+ u32 debobs_4;
+ u32 debobs_5;
+ u32 debobs_6;
+ u32 debobs_7;
+ u32 debobs_8;
+ u32 prog_io0;
+ u32 prog_io1;
+ u32 dss_dpll_spreading;
+ u32 core_dpll_spreading;
+ u32 per_dpll_spreading;
+ u32 usbhost_dpll_spreading;
+ u32 pbias_lite;
+ u32 temp_sensor;
+ u32 sramldo4;
+ u32 sramldo5;
+ u32 csi;
+};
+
+static struct omap3_control_regs control_context;
+#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+
#define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base + (reg))
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
@@ -62,3 +178,268 @@ void omap_ctrl_writel(u32 val, u16 offset)
__raw_writel(val, OMAP_CTRL_REGADDR(offset));
}
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+/*
+ * Clears the scratchpad contents in case of cold boot-
+ * called during bootup
+ */
+void omap3_clear_scratchpad_contents(void)
+{
+ u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
+ u32 *v_addr;
+ u32 offset = 0;
+ v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
+ if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
+ OMAP3430_GLOBAL_COLD_RST) {
+ for ( ; offset <= max_offset; offset += 0x4)
+ __raw_writel(0x0, (v_addr + offset));
+ prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST, OMAP3430_GR_MOD,
+ OMAP3_PRM_RSTST_OFFSET);
+ }
+}
+
+/* Populate the scratchpad structure with restore structure */
+void omap3_save_scratchpad_contents(void)
+{
+ void * __iomem scratchpad_address;
+ u32 arm_context_addr;
+ struct omap3_scratchpad scratchpad_contents;
+ struct omap3_scratchpad_prcm_block prcm_block_contents;
+ struct omap3_scratchpad_sdrc_block sdrc_block_contents;
+
+ /* Populate the Scratchpad contents */
+ scratchpad_contents.boot_config_ptr = 0x0;
+ if (omap_rev() != OMAP3430_REV_ES3_0 &&
+ omap_rev() != OMAP3430_REV_ES3_1)
+ scratchpad_contents.public_restore_ptr =
+ virt_to_phys(get_restore_pointer());
+ else
+ scratchpad_contents.public_restore_ptr =
+ virt_to_phys(get_es3_restore_pointer());
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+ scratchpad_contents.secure_ram_restore_ptr = 0x0;
+ else
+ scratchpad_contents.secure_ram_restore_ptr =
+ (u32) __pa(omap3_secure_ram_storage);
+ scratchpad_contents.sdrc_module_semaphore = 0x0;
+ scratchpad_contents.prcm_block_offset = 0x2C;
+ scratchpad_contents.sdrc_block_offset = 0x64;
+
+ /* Populate the PRCM block contents */
+ prcm_block_contents.prm_clksrc_ctrl = prm_read_mod_reg(OMAP3430_GR_MOD,
+ OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+ prcm_block_contents.prm_clksel = prm_read_mod_reg(OMAP3430_CCR_MOD,
+ OMAP3_PRM_CLKSEL_OFFSET);
+ prcm_block_contents.cm_clksel_core =
+ cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
+ prcm_block_contents.cm_clksel_wkup =
+ cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
+ prcm_block_contents.cm_clken_pll =
+ cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+ prcm_block_contents.cm_autoidle_pll =
+ cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+ prcm_block_contents.cm_clksel1_pll =
+ cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
+ prcm_block_contents.cm_clksel2_pll =
+ cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
+ prcm_block_contents.cm_clksel3_pll =
+ cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
+ prcm_block_contents.cm_clken_pll_mpu =
+ cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
+ prcm_block_contents.cm_autoidle_pll_mpu =
+ cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+ prcm_block_contents.cm_clksel1_pll_mpu =
+ cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
+ prcm_block_contents.cm_clksel2_pll_mpu =
+ cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
+ prcm_block_contents.prcm_block_size = 0x0;
+
+ /* Populate the SDRC block contents */
+ sdrc_block_contents.sysconfig =
+ (sdrc_read_reg(SDRC_SYSCONFIG) & 0xFFFF);
+ sdrc_block_contents.cs_cfg =
+ (sdrc_read_reg(SDRC_CS_CFG) & 0xFFFF);
+ sdrc_block_contents.sharing =
+ (sdrc_read_reg(SDRC_SHARING) & 0xFFFF);
+ sdrc_block_contents.err_type =
+ (sdrc_read_reg(SDRC_ERR_TYPE) & 0xFFFF);
+ sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL);
+ sdrc_block_contents.dll_b_ctrl = 0x0;
+ /*
+ * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should
+ * be programed to issue automatic self refresh on timeout
+ * of AUTO_CNT = 1 prior to any transition to OFF mode.
+ */
+ if ((omap_type() != OMAP2_DEVICE_TYPE_GP)
+ && (omap_rev() >= OMAP3430_REV_ES3_0))
+ sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) &
+ ~(SDRC_POWER_AUTOCOUNT_MASK|
+ SDRC_POWER_CLKCTRL_MASK)) |
+ (1 << SDRC_POWER_AUTOCOUNT_SHIFT) |
+ SDRC_SELF_REFRESH_ON_AUTOCOUNT;
+ else
+ sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER);
+
+ sdrc_block_contents.cs_0 = 0x0;
+ sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0);
+ sdrc_block_contents.mr_0 = (sdrc_read_reg(SDRC_MR_0) & 0xFFFF);
+ sdrc_block_contents.emr_1_0 = 0x0;
+ sdrc_block_contents.emr_2_0 = 0x0;
+ sdrc_block_contents.emr_3_0 = 0x0;
+ sdrc_block_contents.actim_ctrla_0 =
+ sdrc_read_reg(SDRC_ACTIM_CTRL_A_0);
+ sdrc_block_contents.actim_ctrlb_0 =
+ sdrc_read_reg(SDRC_ACTIM_CTRL_B_0);
+ sdrc_block_contents.rfr_ctrl_0 =
+ sdrc_read_reg(SDRC_RFR_CTRL_0);
+ sdrc_block_contents.cs_1 = 0x0;
+ sdrc_block_contents.mcfg_1 = sdrc_read_reg(SDRC_MCFG_1);
+ sdrc_block_contents.mr_1 = sdrc_read_reg(SDRC_MR_1) & 0xFFFF;
+ sdrc_block_contents.emr_1_1 = 0x0;
+ sdrc_block_contents.emr_2_1 = 0x0;
+ sdrc_block_contents.emr_3_1 = 0x0;
+ sdrc_block_contents.actim_ctrla_1 =
+ sdrc_read_reg(SDRC_ACTIM_CTRL_A_1);
+ sdrc_block_contents.actim_ctrlb_1 =
+ sdrc_read_reg(SDRC_ACTIM_CTRL_B_1);
+ sdrc_block_contents.rfr_ctrl_1 =
+ sdrc_read_reg(SDRC_RFR_CTRL_1);
+ sdrc_block_contents.dcdl_1_ctrl = 0x0;
+ sdrc_block_contents.dcdl_2_ctrl = 0x0;
+ sdrc_block_contents.flags = 0x0;
+ sdrc_block_contents.block_size = 0x0;
+
+ arm_context_addr = virt_to_phys(omap3_arm_context);
+
+ /* Copy all the contents to the scratchpad location */
+ scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+ memcpy_toio(scratchpad_address, &scratchpad_contents,
+ sizeof(scratchpad_contents));
+ /* Scratchpad contents being 32 bits, a divide by 4 done here */
+ memcpy_toio(scratchpad_address +
+ scratchpad_contents.prcm_block_offset,
+ &prcm_block_contents, sizeof(prcm_block_contents));
+ memcpy_toio(scratchpad_address +
+ scratchpad_contents.sdrc_block_offset,
+ &sdrc_block_contents, sizeof(sdrc_block_contents));
+ /*
+ * Copies the address of the location in SDRAM where ARM
+ * registers get saved during a MPU OFF transition.
+ */
+ memcpy_toio(scratchpad_address +
+ scratchpad_contents.sdrc_block_offset +
+ sizeof(sdrc_block_contents), &arm_context_addr, 4);
+}
+
+void omap3_control_save_context(void)
+{
+ control_context.sysconfig = omap_ctrl_readl(OMAP2_CONTROL_SYSCONFIG);
+ control_context.devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+ control_context.mem_dftrw0 =
+ omap_ctrl_readl(OMAP343X_CONTROL_MEM_DFTRW0);
+ control_context.mem_dftrw1 =
+ omap_ctrl_readl(OMAP343X_CONTROL_MEM_DFTRW1);
+ control_context.msuspendmux_0 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_0);
+ control_context.msuspendmux_1 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_1);
+ control_context.msuspendmux_2 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_2);
+ control_context.msuspendmux_3 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_3);
+ control_context.msuspendmux_4 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_4);
+ control_context.msuspendmux_5 =
+ omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_5);
+ control_context.sec_ctrl = omap_ctrl_readl(OMAP2_CONTROL_SEC_CTRL);
+ control_context.devconf1 = omap_ctrl_readl(OMAP343X_CONTROL_DEVCONF1);
+ control_context.csirxfe = omap_ctrl_readl(OMAP343X_CONTROL_CSIRXFE);
+ control_context.iva2_bootaddr =
+ omap_ctrl_readl(OMAP343X_CONTROL_IVA2_BOOTADDR);
+ control_context.iva2_bootmod =
+ omap_ctrl_readl(OMAP343X_CONTROL_IVA2_BOOTMOD);
+ control_context.debobs_0 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(0));
+ control_context.debobs_1 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(1));
+ control_context.debobs_2 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(2));
+ control_context.debobs_3 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(3));
+ control_context.debobs_4 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(4));
+ control_context.debobs_5 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(5));
+ control_context.debobs_6 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(6));
+ control_context.debobs_7 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(7));
+ control_context.debobs_8 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(8));
+ control_context.prog_io0 = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO0);
+ control_context.prog_io1 = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO1);
+ control_context.dss_dpll_spreading =
+ omap_ctrl_readl(OMAP343X_CONTROL_DSS_DPLL_SPREADING);
+ control_context.core_dpll_spreading =
+ omap_ctrl_readl(OMAP343X_CONTROL_CORE_DPLL_SPREADING);
+ control_context.per_dpll_spreading =
+ omap_ctrl_readl(OMAP343X_CONTROL_PER_DPLL_SPREADING);
+ control_context.usbhost_dpll_spreading =
+ omap_ctrl_readl(OMAP343X_CONTROL_USBHOST_DPLL_SPREADING);
+ control_context.pbias_lite =
+ omap_ctrl_readl(OMAP343X_CONTROL_PBIAS_LITE);
+ control_context.temp_sensor =
+ omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR);
+ control_context.sramldo4 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO4);
+ control_context.sramldo5 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO5);
+ control_context.csi = omap_ctrl_readl(OMAP343X_CONTROL_CSI);
+ return;
+}
+
+void omap3_control_restore_context(void)
+{
+ omap_ctrl_writel(control_context.sysconfig, OMAP2_CONTROL_SYSCONFIG);
+ omap_ctrl_writel(control_context.devconf0, OMAP2_CONTROL_DEVCONF0);
+ omap_ctrl_writel(control_context.mem_dftrw0,
+ OMAP343X_CONTROL_MEM_DFTRW0);
+ omap_ctrl_writel(control_context.mem_dftrw1,
+ OMAP343X_CONTROL_MEM_DFTRW1);
+ omap_ctrl_writel(control_context.msuspendmux_0,
+ OMAP2_CONTROL_MSUSPENDMUX_0);
+ omap_ctrl_writel(control_context.msuspendmux_1,
+ OMAP2_CONTROL_MSUSPENDMUX_1);
+ omap_ctrl_writel(control_context.msuspendmux_2,
+ OMAP2_CONTROL_MSUSPENDMUX_2);
+ omap_ctrl_writel(control_context.msuspendmux_3,
+ OMAP2_CONTROL_MSUSPENDMUX_3);
+ omap_ctrl_writel(control_context.msuspendmux_4,
+ OMAP2_CONTROL_MSUSPENDMUX_4);
+ omap_ctrl_writel(control_context.msuspendmux_5,
+ OMAP2_CONTROL_MSUSPENDMUX_5);
+ omap_ctrl_writel(control_context.sec_ctrl, OMAP2_CONTROL_SEC_CTRL);
+ omap_ctrl_writel(control_context.devconf1, OMAP343X_CONTROL_DEVCONF1);
+ omap_ctrl_writel(control_context.csirxfe, OMAP343X_CONTROL_CSIRXFE);
+ omap_ctrl_writel(control_context.iva2_bootaddr,
+ OMAP343X_CONTROL_IVA2_BOOTADDR);
+ omap_ctrl_writel(control_context.iva2_bootmod,
+ OMAP343X_CONTROL_IVA2_BOOTMOD);
+ omap_ctrl_writel(control_context.debobs_0, OMAP343X_CONTROL_DEBOBS(0));
+ omap_ctrl_writel(control_context.debobs_1, OMAP343X_CONTROL_DEBOBS(1));
+ omap_ctrl_writel(control_context.debobs_2, OMAP343X_CONTROL_DEBOBS(2));
+ omap_ctrl_writel(control_context.debobs_3, OMAP343X_CONTROL_DEBOBS(3));
+ omap_ctrl_writel(control_context.debobs_4, OMAP343X_CONTROL_DEBOBS(4));
+ omap_ctrl_writel(control_context.debobs_5, OMAP343X_CONTROL_DEBOBS(5));
+ omap_ctrl_writel(control_context.debobs_6, OMAP343X_CONTROL_DEBOBS(6));
+ omap_ctrl_writel(control_context.debobs_7, OMAP343X_CONTROL_DEBOBS(7));
+ omap_ctrl_writel(control_context.debobs_8, OMAP343X_CONTROL_DEBOBS(8));
+ omap_ctrl_writel(control_context.prog_io0, OMAP343X_CONTROL_PROG_IO0);
+ omap_ctrl_writel(control_context.prog_io1, OMAP343X_CONTROL_PROG_IO1);
+ omap_ctrl_writel(control_context.dss_dpll_spreading,
+ OMAP343X_CONTROL_DSS_DPLL_SPREADING);
+ omap_ctrl_writel(control_context.core_dpll_spreading,
+ OMAP343X_CONTROL_CORE_DPLL_SPREADING);
+ omap_ctrl_writel(control_context.per_dpll_spreading,
+ OMAP343X_CONTROL_PER_DPLL_SPREADING);
+ omap_ctrl_writel(control_context.usbhost_dpll_spreading,
+ OMAP343X_CONTROL_USBHOST_DPLL_SPREADING);
+ omap_ctrl_writel(control_context.pbias_lite,
+ OMAP343X_CONTROL_PBIAS_LITE);
+ omap_ctrl_writel(control_context.temp_sensor,
+ OMAP343X_CONTROL_TEMP_SENSOR);
+ omap_ctrl_writel(control_context.sramldo4, OMAP343X_CONTROL_SRAMLDO4);
+ omap_ctrl_writel(control_context.sramldo5, OMAP343X_CONTROL_SRAMLDO5);
+ omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);
+ return;
+}
+#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 004da696ace7..7d687845f391 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -62,6 +62,33 @@
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE 2
+/* Structure to save gpmc cs context */
+struct gpmc_cs_config {
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 config4;
+ u32 config5;
+ u32 config6;
+ u32 config7;
+ int is_valid;
+};
+
+/*
+ * Structure to save/restore gpmc context
+ * to support core off on OMAP3
+ */
+struct omap3_gpmc_regs {
+ u32 sysconfig;
+ u32 irqenable;
+ u32 timeout_ctrl;
+ u32 config;
+ u32 prefetch_config1;
+ u32 prefetch_config2;
+ u32 prefetch_control;
+ struct gpmc_cs_config cs_context[GPMC_CS_NUM];
+};
+
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -261,7 +288,7 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
l &= ~(0x0f << 8);
l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
- l |= 1 << 6; /* CSVALID */
+ l |= GPMC_CONFIG7_CSVALID;
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
}
@@ -270,7 +297,7 @@ static void gpmc_cs_disable_mem(int cs)
u32 l;
l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
- l &= ~(1 << 6); /* CSVALID */
+ l &= ~GPMC_CONFIG7_CSVALID;
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
}
@@ -290,7 +317,7 @@ static int gpmc_cs_mem_enabled(int cs)
u32 l;
l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
- return l & (1 << 6);
+ return l & GPMC_CONFIG7_CSVALID;
}
int gpmc_cs_set_reserved(int cs, int reserved)
@@ -516,3 +543,68 @@ void __init gpmc_init(void)
gpmc_write_reg(GPMC_SYSCONFIG, l);
gpmc_mem_init();
}
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct omap3_gpmc_regs gpmc_context;
+
+void omap3_gpmc_save_context()
+{
+ int i;
+ gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
+ gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
+ gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
+ gpmc_context.config = gpmc_read_reg(GPMC_CONFIG);
+ gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+ gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
+ gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
+ for (i = 0; i < GPMC_CS_NUM; i++) {
+ gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
+ if (gpmc_context.cs_context[i].is_valid) {
+ gpmc_context.cs_context[i].config1 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
+ gpmc_context.cs_context[i].config2 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
+ gpmc_context.cs_context[i].config3 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
+ gpmc_context.cs_context[i].config4 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
+ gpmc_context.cs_context[i].config5 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
+ gpmc_context.cs_context[i].config6 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
+ gpmc_context.cs_context[i].config7 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
+ }
+ }
+}
+
+void omap3_gpmc_restore_context()
+{
+ int i;
+ gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
+ gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
+ gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
+ gpmc_write_reg(GPMC_CONFIG, gpmc_context.config);
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
+ for (i = 0; i < GPMC_CS_NUM; i++) {
+ if (gpmc_context.cs_context[i].is_valid) {
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
+ gpmc_context.cs_context[i].config1);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
+ gpmc_context.cs_context[i].config2);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
+ gpmc_context.cs_context[i].config3);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
+ gpmc_context.cs_context[i].config4);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
+ gpmc_context.cs_context[i].config5);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
+ gpmc_context.cs_context[i].config6);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
+ gpmc_context.cs_context[i].config7);
+ }
+ }
+}
+#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 1db121f437d2..e9bc782fa414 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -25,6 +25,10 @@
#define INTC_SYSSTATUS 0x0014
#define INTC_SIR 0x0040
#define INTC_CONTROL 0x0048
+#define INTC_PROTECTION 0x004C
+#define INTC_IDLE 0x0050
+#define INTC_THRESHOLD 0x0068
+#define INTC_MIR0 0x0084
#define INTC_MIR_CLEAR0 0x0088
#define INTC_MIR_SET0 0x008c
#define INTC_PENDING_IRQ0 0x0098
@@ -48,6 +52,18 @@ static struct omap_irq_bank {
},
};
+/* Structure to save interrupt controller context */
+struct omap3_intc_regs {
+ u32 sysconfig;
+ u32 protection;
+ u32 idle;
+ u32 threshold;
+ u32 ilr[INTCPS_NR_IRQS];
+ u32 mir[INTCPS_NR_MIR_REGS];
+};
+
+static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
+
/* INTC bank register get/set */
static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
@@ -209,3 +225,53 @@ void __init omap_init_irq(void)
}
}
+#ifdef CONFIG_ARCH_OMAP3
+void omap_intc_save_context(void)
+{
+ int ind = 0, i = 0;
+ for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
+ struct omap_irq_bank *bank = irq_banks + ind;
+ intc_context[ind].sysconfig =
+ intc_bank_read_reg(bank, INTC_SYSCONFIG);
+ intc_context[ind].protection =
+ intc_bank_read_reg(bank, INTC_PROTECTION);
+ intc_context[ind].idle =
+ intc_bank_read_reg(bank, INTC_IDLE);
+ intc_context[ind].threshold =
+ intc_bank_read_reg(bank, INTC_THRESHOLD);
+ for (i = 0; i < INTCPS_NR_IRQS; i++)
+ intc_context[ind].ilr[i] =
+ intc_bank_read_reg(bank, (0x100 + 0x4*i));
+ for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
+ intc_context[ind].mir[i] =
+ intc_bank_read_reg(&irq_banks[0], INTC_MIR0 +
+ (0x20 * i));
+ }
+}
+
+void omap_intc_restore_context(void)
+{
+ int ind = 0, i = 0;
+
+ for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
+ struct omap_irq_bank *bank = irq_banks + ind;
+ intc_bank_write_reg(intc_context[ind].sysconfig,
+ bank, INTC_SYSCONFIG);
+ intc_bank_write_reg(intc_context[ind].sysconfig,
+ bank, INTC_SYSCONFIG);
+ intc_bank_write_reg(intc_context[ind].protection,
+ bank, INTC_PROTECTION);
+ intc_bank_write_reg(intc_context[ind].idle,
+ bank, INTC_IDLE);
+ intc_bank_write_reg(intc_context[ind].threshold,
+ bank, INTC_THRESHOLD);
+ for (i = 0; i < INTCPS_NR_IRQS; i++)
+ intc_bank_write_reg(intc_context[ind].ilr[i],
+ bank, (0x100 + 0x4*i));
+ for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
+ intc_bank_write_reg(intc_context[ind].mir[i],
+ &irq_banks[0], INTC_MIR0 + (0x20 * i));
+ }
+ /* MIRs are saved and restore with other PRCM registers */
+}
+#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 7eb2c12c8b7c..8baa30d2acfb 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -527,6 +527,29 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
return 0;
}
+static int option_get(void *data, u64 *val)
+{
+ u32 *option = data;
+
+ *val = *option;
+
+ return 0;
+}
+
+static int option_set(void *data, u64 val)
+{
+ u32 *option = data;
+
+ *option = val;
+
+ if (option == &enable_off_mode)
+ omap3_pm_off_mode_enable(val);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
+
static int __init pm_dbg_init(void)
{
int i;
@@ -569,6 +592,12 @@ static int __init pm_dbg_init(void)
}
+ (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUGO, d,
+ &enable_off_mode, &pm_dbg_option_fops);
+ (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUGO, d,
+ &sleep_while_idle, &pm_dbg_option_fops);
+ (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
+ &wakeup_timer_seconds, &pm_dbg_option_fops);
pm_dbg_init_done = 1;
return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 85b6face5392..7eb769f4ef30 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -13,9 +13,18 @@
#include <plat/powerdomain.h>
+extern u32 enable_off_mode;
+extern u32 sleep_while_idle;
+
+extern void *omap3_secure_ram_storage;
+extern void omap3_pm_off_mode_enable(int);
+
extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
+extern u32 wakeup_timer_seconds;
+extern struct omap_dm_timer *gptimer_wakeup;
+
#ifdef CONFIG_PM_DEBUG
extern void omap2_pm_dump(int mode, int resume, unsigned int us);
extern int omap2_pm_debug;
@@ -36,6 +45,7 @@ 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 save_secure_ram_context(u32 *addr);
+extern void omap3_save_scratchpad_contents(void);
extern unsigned int omap24xx_idle_loop_suspend_sz;
extern unsigned int omap34xx_suspend_sz;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 391054900a6a..01b95eaae75a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -5,6 +5,9 @@
* Tony Lindgren <tony@atomide.com>
* Jouni Hogander
*
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ *
* Copyright (C) 2005 Texas Instruments, Inc.
* Richard Woodruff <r-woodruff2@ti.com>
*
@@ -22,12 +25,20 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/clk.h>
#include <plat/sram.h>
#include <plat/clockdomain.h>
#include <plat/powerdomain.h>
#include <plat/control.h>
#include <plat/serial.h>
+#include <plat/sdrc.h>
+#include <plat/prcm.h>
+#include <plat/gpmc.h>
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+
+#include <asm/tlbflush.h>
#include "cm.h"
#include "cm-regbits-34xx.h"
@@ -35,6 +46,16 @@
#include "prm.h"
#include "pm.h"
+#include "sdrc.h"
+
+/* Scratchpad offsets */
+#define OMAP343X_TABLE_ADDRESS_OFFSET 0x31
+#define OMAP343X_TABLE_VALUE_OFFSET 0x30
+#define OMAP343X_CONTROL_REG_VALUE_OFFSET 0x32
+
+u32 enable_off_mode;
+u32 sleep_while_idle;
+u32 wakeup_timer_seconds;
struct power_state {
struct powerdomain *pwrdm;
@@ -49,7 +70,114 @@ static LIST_HEAD(pwrst_list);
static void (*_omap_sram_idle)(u32 *addr, int save_state);
-static struct powerdomain *mpu_pwrdm;
+static int (*_omap_save_secure_sram)(u32 *addr);
+
+static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
+static struct powerdomain *core_pwrdm, *per_pwrdm;
+static struct powerdomain *cam_pwrdm;
+
+static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+
+static inline void omap3_per_save_context(void)
+{
+ omap_gpio_save_context();
+}
+
+static inline void omap3_per_restore_context(void)
+{
+ omap_gpio_restore_context();
+}
+
+static void omap3_enable_io_chain(void)
+{
+ int timeout = 0;
+
+ if (omap_rev() >= OMAP3430_REV_ES3_1) {
+ prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN);
+ /* Do a readback to assure write has been done */
+ prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+
+ while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+ OMAP3430_ST_IO_CHAIN)) {
+ timeout++;
+ if (timeout > 1000) {
+ printk(KERN_ERR "Wake up daisy chain "
+ "activation failed.\n");
+ return;
+ }
+ prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN,
+ WKUP_MOD, PM_WKST);
+ }
+ }
+}
+
+static void omap3_disable_io_chain(void)
+{
+ if (omap_rev() >= OMAP3430_REV_ES3_1)
+ prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN);
+}
+
+static void omap3_core_save_context(void)
+{
+ u32 control_padconf_off;
+
+ /* Save the padconf registers */
+ control_padconf_off = omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_OFF);
+ control_padconf_off |= START_PADCONF_SAVE;
+ omap_ctrl_writel(control_padconf_off, OMAP343X_CONTROL_PADCONF_OFF);
+ /* wait for the save to complete */
+ while (!omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
+ & PADCONF_SAVE_DONE)
+ ;
+ /* Save the Interrupt controller context */
+ omap_intc_save_context();
+ /* Save the GPMC context */
+ omap3_gpmc_save_context();
+ /* Save the system control module context, padconf already save above*/
+ omap3_control_save_context();
+ omap_dma_global_context_save();
+}
+
+static void omap3_core_restore_context(void)
+{
+ /* Restore the control module context, padconf restored by h/w */
+ omap3_control_restore_context();
+ /* Restore the GPMC context */
+ omap3_gpmc_restore_context();
+ /* Restore the interrupt controller context */
+ omap_intc_restore_context();
+ omap_dma_global_context_restore();
+}
+
+/*
+ * FIXME: This function should be called before entering off-mode after
+ * OMAP3 secure services have been accessed. Currently it is only called
+ * once during boot sequence, but this works as we are not using secure
+ * services.
+ */
+static void omap3_save_secure_ram_context(u32 target_mpu_state)
+{
+ u32 ret;
+
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
+ /*
+ * MPU next state must be set to POWER_ON temporarily,
+ * otherwise the WFI executed inside the ROM code
+ * will hang the system.
+ */
+ pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+ ret = _omap_save_secure_sram((u32 *)
+ __pa(omap3_secure_ram_storage));
+ pwrdm_set_next_pwrst(mpu_pwrdm, target_mpu_state);
+ /* Following is for error tracking, it should not happen */
+ if (ret) {
+ printk(KERN_ERR "save_secure_sram() returns %08x\n",
+ ret);
+ while (1)
+ ;
+ }
+ }
+}
/*
* PRCM Interrupt Handler Helper Function
@@ -161,6 +289,35 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void restore_control_register(u32 val)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c1, c0, 0" : : "r" (val));
+}
+
+/* Function to restore the table entry that was modified for enabling MMU */
+static void restore_table_entry(void)
+{
+ u32 *scratchpad_address;
+ u32 previous_value, control_reg_value;
+ u32 *address;
+
+ scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+
+ /* Get address of entry that was modified */
+ address = (u32 *)__raw_readl(scratchpad_address +
+ OMAP343X_TABLE_ADDRESS_OFFSET);
+ /* Get the previous value which needs to be restored */
+ previous_value = __raw_readl(scratchpad_address +
+ OMAP343X_TABLE_VALUE_OFFSET);
+ address = __va(address);
+ *address = previous_value;
+ flush_tlb_all();
+ control_reg_value = __raw_readl(scratchpad_address
+ + OMAP343X_CONTROL_REG_VALUE_OFFSET);
+ /* This will enable caches and prediction */
+ restore_control_register(control_reg_value);
+}
+
static void omap_sram_idle(void)
{
/* Variable to tell what needs to be saved and restored
@@ -169,17 +326,32 @@ static void omap_sram_idle(void)
/* save_state = 1 => Only L1 and logic lost */
/* save_state = 2 => Only L2 lost */
/* save_state = 3 => L1, L2 and logic lost */
- int save_state = 0, mpu_next_state;
+ int save_state = 0;
+ int mpu_next_state = PWRDM_POWER_ON;
+ int per_next_state = PWRDM_POWER_ON;
+ int core_next_state = PWRDM_POWER_ON;
+ int core_prev_state, per_prev_state;
+ u32 sdrc_pwr = 0;
+ int per_state_modified = 0;
if (!_omap_sram_idle)
return;
+ pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
+ pwrdm_clear_all_prev_pwrst(neon_pwrdm);
+ pwrdm_clear_all_prev_pwrst(core_pwrdm);
+ pwrdm_clear_all_prev_pwrst(per_pwrdm);
+
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
+ case PWRDM_POWER_ON:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
break;
+ case PWRDM_POWER_OFF:
+ save_state = 3;
+ break;
default:
/* Invalid state */
printk(KERN_ERR "Invalid mpu state in sram_idle\n");
@@ -187,21 +359,108 @@ static void omap_sram_idle(void)
}
pwrdm_pre_transition();
- omap2_gpio_prepare_for_retention();
- omap_uart_prepare_idle(0);
- omap_uart_prepare_idle(1);
- omap_uart_prepare_idle(2);
+ /* NEON control */
+ if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
+ set_pwrdm_state(neon_pwrdm, mpu_next_state);
+
+ /* PER */
+ per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
+ core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
+ if (per_next_state < PWRDM_POWER_ON) {
+ omap_uart_prepare_idle(2);
+ omap2_gpio_prepare_for_retention();
+ if (per_next_state == PWRDM_POWER_OFF) {
+ if (core_next_state == PWRDM_POWER_ON) {
+ per_next_state = PWRDM_POWER_RET;
+ pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
+ per_state_modified = 1;
+ } else
+ omap3_per_save_context();
+ }
+ }
+
+ if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
+ omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+
+ /* CORE */
+ if (core_next_state < PWRDM_POWER_ON) {
+ omap_uart_prepare_idle(0);
+ omap_uart_prepare_idle(1);
+ if (core_next_state == PWRDM_POWER_OFF) {
+ omap3_core_save_context();
+ omap3_prcm_save_context();
+ }
+ /* Enable IO-PAD and IO-CHAIN wakeups */
+ prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+ omap3_enable_io_chain();
+ }
- _omap_sram_idle(NULL, save_state);
+ /*
+ * On EMU/HS devices ROM code restores a SRDC value
+ * from scratchpad which has automatic self refresh on timeout
+ * of AUTO_CNT = 1 enabled. This takes care of errata 1.142.
+ * Hence store/restore the SDRC_POWER register here.
+ */
+ if (omap_rev() >= OMAP3430_REV_ES3_0 &&
+ omap_type() != OMAP2_DEVICE_TYPE_GP &&
+ core_next_state == PWRDM_POWER_OFF)
+ sdrc_pwr = sdrc_read_reg(SDRC_POWER);
+
+ /*
+ * omap3_arm_context is the location where ARM registers
+ * get saved. The restore path then reads from this
+ * location and restores them back.
+ */
+ _omap_sram_idle(omap3_arm_context, save_state);
cpu_init();
- omap_uart_resume_idle(2);
- omap_uart_resume_idle(1);
- omap_uart_resume_idle(0);
- omap2_gpio_resume_after_retention();
+ /* Restore normal SDRC POWER settings */
+ if (omap_rev() >= OMAP3430_REV_ES3_0 &&
+ omap_type() != OMAP2_DEVICE_TYPE_GP &&
+ core_next_state == PWRDM_POWER_OFF)
+ sdrc_write_reg(sdrc_pwr, SDRC_POWER);
+
+ /* Restore table entry modified during MMU restoration */
+ if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
+ restore_table_entry();
+
+ /* CORE */
+ if (core_next_state < PWRDM_POWER_ON) {
+ core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
+ if (core_prev_state == PWRDM_POWER_OFF) {
+ omap3_core_restore_context();
+ omap3_prcm_restore_context();
+ omap3_sram_restore_context();
+ omap2_sms_restore_context();
+ }
+ omap_uart_resume_idle(0);
+ omap_uart_resume_idle(1);
+ if (core_next_state == PWRDM_POWER_OFF)
+ prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF,
+ OMAP3430_GR_MOD,
+ OMAP3_PRM_VOLTCTRL_OFFSET);
+ }
+
+ /* PER */
+ if (per_next_state < PWRDM_POWER_ON) {
+ per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
+ if (per_prev_state == PWRDM_POWER_OFF)
+ omap3_per_restore_context();
+ omap2_gpio_resume_after_retention();
+ omap_uart_resume_idle(2);
+ if (per_state_modified)
+ pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
+ }
+
+ /* Disable IO-PAD and IO-CHAIN wakeup */
+ if (core_next_state < PWRDM_POWER_ON) {
+ prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+ omap3_disable_io_chain();
+ }
pwrdm_post_transition();
+ omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
}
/*
@@ -246,6 +505,8 @@ static int omap3_fclks_active(void)
static int omap3_can_sleep(void)
{
+ if (!sleep_while_idle)
+ return 0;
if (!omap_uart_can_sleep())
return 0;
if (omap3_fclks_active())
@@ -319,6 +580,22 @@ out:
#ifdef CONFIG_SUSPEND
static suspend_state_t suspend_state;
+static void omap2_pm_wakeup_on_timer(u32 seconds)
+{
+ u32 tick_rate, cycles;
+
+ if (!seconds)
+ return;
+
+ tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+ cycles = tick_rate * seconds;
+ omap_dm_timer_stop(gptimer_wakeup);
+ omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+ pr_info("PM: Resume timer in %d secs (%d ticks at %d ticks/sec.)\n",
+ seconds, cycles, tick_rate);
+}
+
static int omap3_pm_prepare(void)
{
disable_hlt();
@@ -330,6 +607,9 @@ static int omap3_pm_suspend(void)
struct power_state *pwrst;
int state, ret = 0;
+ if (wakeup_timer_seconds)
+ omap2_pm_wakeup_on_timer(wakeup_timer_seconds);
+
/* Read current next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node)
pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
@@ -690,6 +970,22 @@ static void __init prcm_setup_regs(void)
omap3_d2d_idle();
}
+void omap3_pm_off_mode_enable(int enable)
+{
+ struct power_state *pwrst;
+ u32 state;
+
+ if (enable)
+ state = PWRDM_POWER_OFF;
+ else
+ state = PWRDM_POWER_RET;
+
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ pwrst->next_state = state;
+ set_pwrdm_state(pwrst->pwrdm, state);
+ }
+}
+
int omap3_pm_get_suspend_state(struct powerdomain *pwrdm)
{
struct power_state *pwrst;
@@ -749,6 +1045,15 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
+void omap_push_sram_idle(void)
+{
+ _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);
+}
+
static int __init omap3_pm_init(void)
{
struct power_state *pwrst, *tmp;
@@ -786,15 +1091,46 @@ static int __init omap3_pm_init(void)
goto err2;
}
- _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
- omap34xx_cpu_suspend_sz);
+ neon_pwrdm = pwrdm_lookup("neon_pwrdm");
+ per_pwrdm = pwrdm_lookup("per_pwrdm");
+ core_pwrdm = pwrdm_lookup("core_pwrdm");
+ cam_pwrdm = pwrdm_lookup("cam_pwrdm");
+ omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
pm_idle = omap3_pm_idle;
+ pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
+ /*
+ * REVISIT: This wkdep is only necessary when GPIO2-6 are enabled for
+ * IO-pad wakeup. Otherwise it will unnecessarily waste power
+ * waking up PER with every CORE wakeup - see
+ * http://marc.info/?l=linux-omap&m=121852150710062&w=2
+ */
+ pwrdm_add_wkdep(per_pwrdm, core_pwrdm);
+
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
+ omap3_secure_ram_storage =
+ kmalloc(0x803F, GFP_KERNEL);
+ if (!omap3_secure_ram_storage)
+ printk(KERN_ERR "Memory allocation failed when"
+ "allocating for secure sram context\n");
+
+ local_irq_disable();
+ local_fiq_disable();
+
+ omap_dma_global_context_save();
+ omap3_save_secure_ram_context(PWRDM_POWER_ON);
+ omap_dma_global_context_restore();
+
+ local_irq_enable();
+ local_fiq_enable();
+ }
+
+ omap3_save_scratchpad_contents();
err1:
return ret;
err2:
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
index f70eb2da17e7..fd09b0827df0 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -338,7 +338,13 @@ static struct powerdomain usbhost_pwrdm = {
.sleepdep_srcs = dss_per_usbhost_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
- .flags = PWRDM_HAS_HDWR_SAR, /* for USBHOST ctrlr only */
+ /*
+ * REVISIT: Enabling usb host save and restore mechanism seems to
+ * leave the usb host domain permanently in ACTIVE mode after
+ * changing the usb host power domain state from OFF to active once.
+ * Disabling for now.
+ */
+ /*.flags = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index b0d3ad05be2e..029d376198d4 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -7,6 +7,9 @@
*
* Written by Tony Lindgren <tony.lindgren@nokia.com>
*
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ *
* Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -21,8 +24,11 @@
#include <plat/common.h>
#include <plat/prcm.h>
+#include <plat/irqs.h>
+#include <plat/control.h>
#include "clock.h"
+#include "cm.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
@@ -31,6 +37,89 @@ static void __iomem *cm_base;
#define MAX_MODULE_ENABLE_WAIT 100000
+struct omap3_prcm_regs {
+ u32 control_padconf_sys_nirq;
+ u32 iva2_cm_clksel1;
+ u32 iva2_cm_clksel2;
+ u32 cm_sysconfig;
+ u32 sgx_cm_clksel;
+ u32 wkup_cm_clksel;
+ u32 dss_cm_clksel;
+ u32 cam_cm_clksel;
+ u32 per_cm_clksel;
+ u32 emu_cm_clksel;
+ u32 emu_cm_clkstctrl;
+ u32 pll_cm_autoidle2;
+ u32 pll_cm_clksel4;
+ u32 pll_cm_clksel5;
+ u32 pll_cm_clken;
+ u32 pll_cm_clken2;
+ u32 cm_polctrl;
+ u32 iva2_cm_fclken;
+ u32 iva2_cm_clken_pll;
+ u32 core_cm_fclken1;
+ u32 core_cm_fclken3;
+ u32 sgx_cm_fclken;
+ u32 wkup_cm_fclken;
+ u32 dss_cm_fclken;
+ u32 cam_cm_fclken;
+ u32 per_cm_fclken;
+ u32 usbhost_cm_fclken;
+ u32 core_cm_iclken1;
+ u32 core_cm_iclken2;
+ u32 core_cm_iclken3;
+ u32 sgx_cm_iclken;
+ u32 wkup_cm_iclken;
+ u32 dss_cm_iclken;
+ u32 cam_cm_iclken;
+ u32 per_cm_iclken;
+ u32 usbhost_cm_iclken;
+ u32 iva2_cm_autiidle2;
+ u32 mpu_cm_autoidle2;
+ u32 pll_cm_autoidle;
+ u32 iva2_cm_clkstctrl;
+ u32 mpu_cm_clkstctrl;
+ u32 core_cm_clkstctrl;
+ u32 sgx_cm_clkstctrl;
+ u32 dss_cm_clkstctrl;
+ u32 cam_cm_clkstctrl;
+ u32 per_cm_clkstctrl;
+ u32 neon_cm_clkstctrl;
+ u32 usbhost_cm_clkstctrl;
+ u32 core_cm_autoidle1;
+ u32 core_cm_autoidle2;
+ u32 core_cm_autoidle3;
+ u32 wkup_cm_autoidle;
+ u32 dss_cm_autoidle;
+ u32 cam_cm_autoidle;
+ u32 per_cm_autoidle;
+ u32 usbhost_cm_autoidle;
+ u32 sgx_cm_sleepdep;
+ u32 dss_cm_sleepdep;
+ u32 cam_cm_sleepdep;
+ u32 per_cm_sleepdep;
+ u32 usbhost_cm_sleepdep;
+ u32 cm_clkout_ctrl;
+ u32 prm_clkout_ctrl;
+ u32 sgx_pm_wkdep;
+ u32 dss_pm_wkdep;
+ u32 cam_pm_wkdep;
+ u32 per_pm_wkdep;
+ u32 neon_pm_wkdep;
+ u32 usbhost_pm_wkdep;
+ u32 core_pm_mpugrpsel1;
+ u32 iva2_pm_ivagrpsel1;
+ u32 core_pm_mpugrpsel3;
+ u32 core_pm_ivagrpsel3;
+ u32 wkup_pm_mpugrpsel;
+ u32 wkup_pm_ivagrpsel;
+ u32 per_pm_mpugrpsel;
+ u32 per_pm_ivagrpsel;
+ u32 wkup_pm_wken;
+};
+
+struct omap3_prcm_regs prcm_context;
+
u32 omap_prcm_get_reset_sources(void)
{
/* XXX This presumably needs modification for 34XX */
@@ -46,9 +135,18 @@ void omap_prcm_arch_reset(char mode)
if (cpu_is_omap24xx())
prcm_offs = WKUP_MOD;
- else if (cpu_is_omap34xx())
+ else if (cpu_is_omap34xx()) {
+ u32 l;
+
prcm_offs = OMAP3430_GR_MOD;
- else
+ l = ('B' << 24) | ('M' << 16) | mode;
+ /* Reserve the first word in scratchpad for communicating
+ * with the boot ROM. A pointer to a data structure
+ * describing the boot process can be stored there,
+ * cf. OMAP34xx TRM, Initialization / Software Booting
+ * Configuration. */
+ omap_writel(l, OMAP343X_SCRATCHPAD + 4);
+ } else
WARN_ON(1);
prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL);
@@ -168,3 +266,308 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
prm_base = omap2_globals->prm;
cm_base = omap2_globals->cm;
}
+
+#ifdef CONFIG_ARCH_OMAP3
+void omap3_prcm_save_context(void)
+{
+ prcm_context.control_padconf_sys_nirq =
+ omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
+ prcm_context.iva2_cm_clksel1 =
+ cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
+ prcm_context.iva2_cm_clksel2 =
+ cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
+ prcm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
+ prcm_context.sgx_cm_clksel =
+ cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
+ prcm_context.wkup_cm_clksel = cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
+ prcm_context.dss_cm_clksel =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
+ prcm_context.cam_cm_clksel =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
+ prcm_context.per_cm_clksel =
+ cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
+ prcm_context.emu_cm_clksel =
+ cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
+ prcm_context.emu_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSTCTRL);
+ prcm_context.pll_cm_autoidle2 =
+ cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
+ prcm_context.pll_cm_clksel4 =
+ cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
+ prcm_context.pll_cm_clksel5 =
+ cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
+ prcm_context.pll_cm_clken =
+ cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+ prcm_context.pll_cm_clken2 =
+ cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
+ prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
+ prcm_context.iva2_cm_fclken =
+ cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
+ prcm_context.iva2_cm_clken_pll = cm_read_mod_reg(OMAP3430_IVA2_MOD,
+ OMAP3430_CM_CLKEN_PLL);
+ prcm_context.core_cm_fclken1 =
+ cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+ prcm_context.core_cm_fclken3 =
+ cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+ prcm_context.sgx_cm_fclken =
+ cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
+ prcm_context.wkup_cm_fclken =
+ cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
+ prcm_context.dss_cm_fclken =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
+ prcm_context.cam_cm_fclken =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
+ prcm_context.per_cm_fclken =
+ cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
+ prcm_context.usbhost_cm_fclken =
+ cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+ prcm_context.core_cm_iclken1 =
+ cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
+ prcm_context.core_cm_iclken2 =
+ cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
+ prcm_context.core_cm_iclken3 =
+ cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
+ prcm_context.sgx_cm_iclken =
+ cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
+ prcm_context.wkup_cm_iclken =
+ cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
+ prcm_context.dss_cm_iclken =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
+ prcm_context.cam_cm_iclken =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
+ prcm_context.per_cm_iclken =
+ cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
+ prcm_context.usbhost_cm_iclken =
+ cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+ prcm_context.iva2_cm_autiidle2 =
+ cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
+ prcm_context.mpu_cm_autoidle2 =
+ cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
+ prcm_context.pll_cm_autoidle =
+ cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+ prcm_context.iva2_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSTCTRL);
+ prcm_context.mpu_cm_clkstctrl =
+ cm_read_mod_reg(MPU_MOD, CM_CLKSTCTRL);
+ prcm_context.core_cm_clkstctrl =
+ cm_read_mod_reg(CORE_MOD, CM_CLKSTCTRL);
+ prcm_context.sgx_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSTCTRL);
+ prcm_context.dss_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSTCTRL);
+ prcm_context.cam_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSTCTRL);
+ prcm_context.per_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSTCTRL);
+ prcm_context.neon_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430_NEON_MOD, CM_CLKSTCTRL);
+ prcm_context.usbhost_cm_clkstctrl =
+ cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
+ prcm_context.core_cm_autoidle1 =
+ cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
+ prcm_context.core_cm_autoidle2 =
+ cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
+ prcm_context.core_cm_autoidle3 =
+ cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
+ prcm_context.wkup_cm_autoidle =
+ cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
+ prcm_context.dss_cm_autoidle =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
+ prcm_context.cam_cm_autoidle =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
+ prcm_context.per_cm_autoidle =
+ cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+ prcm_context.usbhost_cm_autoidle =
+ cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+ prcm_context.sgx_cm_sleepdep =
+ cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP3430_CM_SLEEPDEP);
+ prcm_context.dss_cm_sleepdep =
+ cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
+ prcm_context.cam_cm_sleepdep =
+ cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
+ prcm_context.per_cm_sleepdep =
+ cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
+ prcm_context.usbhost_cm_sleepdep =
+ cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
+ prcm_context.cm_clkout_ctrl = cm_read_mod_reg(OMAP3430_CCR_MOD,
+ OMAP3_CM_CLKOUT_CTRL_OFFSET);
+ prcm_context.prm_clkout_ctrl = prm_read_mod_reg(OMAP3430_CCR_MOD,
+ OMAP3_PRM_CLKOUT_CTRL_OFFSET);
+ prcm_context.sgx_pm_wkdep =
+ prm_read_mod_reg(OMAP3430ES2_SGX_MOD, PM_WKDEP);
+ prcm_context.dss_pm_wkdep =
+ prm_read_mod_reg(OMAP3430_DSS_MOD, PM_WKDEP);
+ prcm_context.cam_pm_wkdep =
+ prm_read_mod_reg(OMAP3430_CAM_MOD, PM_WKDEP);
+ prcm_context.per_pm_wkdep =
+ prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKDEP);
+ prcm_context.neon_pm_wkdep =
+ prm_read_mod_reg(OMAP3430_NEON_MOD, PM_WKDEP);
+ prcm_context.usbhost_pm_wkdep =
+ prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
+ prcm_context.core_pm_mpugrpsel1 =
+ prm_read_mod_reg(CORE_MOD, OMAP3430_PM_MPUGRPSEL1);
+ prcm_context.iva2_pm_ivagrpsel1 =
+ prm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_PM_IVAGRPSEL1);
+ prcm_context.core_pm_mpugrpsel3 =
+ prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_MPUGRPSEL3);
+ prcm_context.core_pm_ivagrpsel3 =
+ prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+ prcm_context.wkup_pm_mpugrpsel =
+ prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
+ prcm_context.wkup_pm_ivagrpsel =
+ prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+ prcm_context.per_pm_mpugrpsel =
+ prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
+ prcm_context.per_pm_ivagrpsel =
+ prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+ prcm_context.wkup_pm_wken = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+ return;
+}
+
+void omap3_prcm_restore_context(void)
+{
+ omap_ctrl_writel(prcm_context.control_padconf_sys_nirq,
+ OMAP343X_CONTROL_PADCONF_SYSNIRQ);
+ cm_write_mod_reg(prcm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
+ CM_CLKSEL1);
+ cm_write_mod_reg(prcm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
+ CM_CLKSEL2);
+ __raw_writel(prcm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
+ cm_write_mod_reg(prcm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
+ CM_CLKSEL);
+ cm_write_mod_reg(prcm_context.wkup_cm_clksel, WKUP_MOD, CM_CLKSEL);
+ cm_write_mod_reg(prcm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
+ CM_CLKSEL);
+ cm_write_mod_reg(prcm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
+ CM_CLKSEL);
+ cm_write_mod_reg(prcm_context.per_cm_clksel, OMAP3430_PER_MOD,
+ CM_CLKSEL);
+ cm_write_mod_reg(prcm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
+ CM_CLKSEL1);
+ cm_write_mod_reg(prcm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.pll_cm_autoidle2, PLL_MOD,
+ CM_AUTOIDLE2);
+ cm_write_mod_reg(prcm_context.pll_cm_clksel4, PLL_MOD,
+ OMAP3430ES2_CM_CLKSEL4);
+ cm_write_mod_reg(prcm_context.pll_cm_clksel5, PLL_MOD,
+ OMAP3430ES2_CM_CLKSEL5);
+ cm_write_mod_reg(prcm_context.pll_cm_clken, PLL_MOD, CM_CLKEN);
+ cm_write_mod_reg(prcm_context.pll_cm_clken2, PLL_MOD,
+ OMAP3430ES2_CM_CLKEN2);
+ __raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
+ cm_write_mod_reg(prcm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
+ CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
+ OMAP3430_CM_CLKEN_PLL);
+ cm_write_mod_reg(prcm_context.core_cm_fclken1, CORE_MOD, CM_FCLKEN1);
+ cm_write_mod_reg(prcm_context.core_cm_fclken3, CORE_MOD,
+ OMAP3430ES2_CM_FCLKEN3);
+ cm_write_mod_reg(prcm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
+ CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
+ CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
+ CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.per_cm_fclken, OMAP3430_PER_MOD,
+ CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.usbhost_cm_fclken,
+ OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+ cm_write_mod_reg(prcm_context.core_cm_iclken1, CORE_MOD, CM_ICLKEN1);
+ cm_write_mod_reg(prcm_context.core_cm_iclken2, CORE_MOD, CM_ICLKEN2);
+ cm_write_mod_reg(prcm_context.core_cm_iclken3, CORE_MOD, CM_ICLKEN3);
+ cm_write_mod_reg(prcm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
+ CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
+ CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
+ CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.per_cm_iclken, OMAP3430_PER_MOD,
+ CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.usbhost_cm_iclken,
+ OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+ cm_write_mod_reg(prcm_context.iva2_cm_autiidle2, OMAP3430_IVA2_MOD,
+ CM_AUTOIDLE2);
+ cm_write_mod_reg(prcm_context.mpu_cm_autoidle2, MPU_MOD, CM_AUTOIDLE2);
+ cm_write_mod_reg(prcm_context.pll_cm_autoidle, PLL_MOD, CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD, CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.core_cm_clkstctrl, CORE_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
+ CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.usbhost_cm_clkstctrl,
+ OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
+ cm_write_mod_reg(prcm_context.core_cm_autoidle1, CORE_MOD,
+ CM_AUTOIDLE1);
+ cm_write_mod_reg(prcm_context.core_cm_autoidle2, CORE_MOD,
+ CM_AUTOIDLE2);
+ cm_write_mod_reg(prcm_context.core_cm_autoidle3, CORE_MOD,
+ CM_AUTOIDLE3);
+ cm_write_mod_reg(prcm_context.wkup_cm_autoidle, WKUP_MOD, CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
+ CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
+ CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.per_cm_autoidle, OMAP3430_PER_MOD,
+ CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.usbhost_cm_autoidle,
+ OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+ cm_write_mod_reg(prcm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
+ OMAP3430_CM_SLEEPDEP);
+ cm_write_mod_reg(prcm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
+ OMAP3430_CM_SLEEPDEP);
+ cm_write_mod_reg(prcm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
+ OMAP3430_CM_SLEEPDEP);
+ cm_write_mod_reg(prcm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
+ OMAP3430_CM_SLEEPDEP);
+ cm_write_mod_reg(prcm_context.usbhost_cm_sleepdep,
+ OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
+ cm_write_mod_reg(prcm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
+ OMAP3_CM_CLKOUT_CTRL_OFFSET);
+ prm_write_mod_reg(prcm_context.prm_clkout_ctrl, OMAP3430_CCR_MOD,
+ OMAP3_PRM_CLKOUT_CTRL_OFFSET);
+ prm_write_mod_reg(prcm_context.sgx_pm_wkdep, OMAP3430ES2_SGX_MOD,
+ PM_WKDEP);
+ prm_write_mod_reg(prcm_context.dss_pm_wkdep, OMAP3430_DSS_MOD,
+ PM_WKDEP);
+ prm_write_mod_reg(prcm_context.cam_pm_wkdep, OMAP3430_CAM_MOD,
+ PM_WKDEP);
+ prm_write_mod_reg(prcm_context.per_pm_wkdep, OMAP3430_PER_MOD,
+ PM_WKDEP);
+ prm_write_mod_reg(prcm_context.neon_pm_wkdep, OMAP3430_NEON_MOD,
+ PM_WKDEP);
+ prm_write_mod_reg(prcm_context.usbhost_pm_wkdep,
+ OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
+ prm_write_mod_reg(prcm_context.core_pm_mpugrpsel1, CORE_MOD,
+ OMAP3430_PM_MPUGRPSEL1);
+ prm_write_mod_reg(prcm_context.iva2_pm_ivagrpsel1, OMAP3430_IVA2_MOD,
+ OMAP3430_PM_IVAGRPSEL1);
+ prm_write_mod_reg(prcm_context.core_pm_mpugrpsel3, CORE_MOD,
+ OMAP3430ES2_PM_MPUGRPSEL3);
+ prm_write_mod_reg(prcm_context.core_pm_ivagrpsel3, CORE_MOD,
+ OMAP3430ES2_PM_IVAGRPSEL3);
+ prm_write_mod_reg(prcm_context.wkup_pm_mpugrpsel, WKUP_MOD,
+ OMAP3430_PM_MPUGRPSEL);
+ prm_write_mod_reg(prcm_context.wkup_pm_ivagrpsel, WKUP_MOD,
+ OMAP3430_PM_IVAGRPSEL);
+ prm_write_mod_reg(prcm_context.per_pm_mpugrpsel, OMAP3430_PER_MOD,
+ OMAP3430_PM_MPUGRPSEL);
+ prm_write_mod_reg(prcm_context.per_pm_ivagrpsel, OMAP3430_PER_MOD,
+ OMAP3430_PM_IVAGRPSEL);
+ prm_write_mod_reg(prcm_context.wkup_pm_wken, WKUP_MOD, PM_WKEN);
+ return;
+}
+#endif
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 9fd03a2ec95c..8f21bae6dc1c 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -365,6 +365,7 @@
/* PM_PREPWSTST_GFX specific bits */
/* PM_WKEN_WKUP specific bits */
+#define OMAP3430_EN_IO_CHAIN (1 << 16)
#define OMAP3430_EN_IO (1 << 8)
#define OMAP3430_EN_GPIO1 (1 << 3)
@@ -373,6 +374,7 @@
/* PM_IVA2GRPSEL_WKUP specific bits */
/* PM_WKST_WKUP specific bits */
+#define OMAP3430_ST_IO_CHAIN (1 << 16)
#define OMAP3430_ST_IO (1 << 8)
/* PRM_CLKSEL */
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index 07000de48f34..9a592199321c 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -37,12 +37,38 @@ static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1;
void __iomem *omap2_sdrc_base;
void __iomem *omap2_sms_base;
+struct omap2_sms_regs {
+ u32 sms_sysconfig;
+};
+
+static struct omap2_sms_regs sms_context;
+
/* SDRC_POWER register bits */
#define SDRC_POWER_EXTCLKDIS_SHIFT 3
#define SDRC_POWER_PWDENA_SHIFT 2
#define SDRC_POWER_PAGEPOLICY_SHIFT 0
/**
+ * omap2_sms_save_context - Save SMS registers
+ *
+ * Save SMS registers that need to be restored after off mode.
+ */
+void omap2_sms_save_context(void)
+{
+ sms_context.sms_sysconfig = sms_read_reg(SMS_SYSCONFIG);
+}
+
+/**
+ * omap2_sms_restore_context - Restore SMS registers
+ *
+ * Restore SMS registers that need to be Restored after off mode.
+ */
+void omap2_sms_restore_context(void)
+{
+ sms_write_reg(sms_context.sms_sysconfig, SMS_SYSCONFIG);
+}
+
+/**
* omap2_sdrc_get_params - return SDRC register values for a given clock rate
* @r: SDRC clock rate (in Hz)
* @sdrc_cs0: chip select 0 ram timings **
@@ -132,4 +158,5 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) |
(1 << SDRC_POWER_PAGEPOLICY_SHIFT);
sdrc_write_reg(l, SDRC_POWER);
+ omap2_sms_save_context();
}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index a5aecffe03ff..72df1b188135 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -155,8 +155,6 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
-static int enable_off_mode; /* to be removed by full off-mode patches */
-
static void omap_uart_save_context(struct omap_uart_state *uart)
{
u16 lcr = 0;
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 6a749f2fea63..15268f8b61de 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -29,20 +29,33 @@
#include <mach/io.h>
#include <plat/control.h>
+#include "cm.h"
#include "prm.h"
#include "sdrc.h"
#define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \
OMAP3430_PM_PREPWSTST)
+#define PM_PREPWSTST_CORE_P 0x48306AE8
#define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \
OMAP3430_PM_PREPWSTST)
-#define PM_PWSTCTRL_MPU_P OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL)
+#define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL
+#define CM_IDLEST1_CORE_V OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
+#define SRAM_BASE_P 0x40200000
+#define CONTROL_STAT 0x480022F0
#define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is
* available */
-#define SCRATCHPAD_BASE_P OMAP343X_CTRL_REGADDR(\
- OMAP343X_CONTROL_MEM_WKUP +\
- SCRATCHPAD_MEM_OFFS)
+#define SCRATCHPAD_BASE_P (OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\
+ + SCRATCHPAD_MEM_OFFS)
#define SDRC_POWER_V OMAP34XX_SDRC_REGADDR(SDRC_POWER)
+#define SDRC_SYSCONFIG_P (OMAP343X_SDRC_BASE + SDRC_SYSCONFIG)
+#define SDRC_MR_0_P (OMAP343X_SDRC_BASE + SDRC_MR_0)
+#define SDRC_EMR2_0_P (OMAP343X_SDRC_BASE + SDRC_EMR2_0)
+#define SDRC_MANUAL_0_P (OMAP343X_SDRC_BASE + SDRC_MANUAL_0)
+#define SDRC_MR_1_P (OMAP343X_SDRC_BASE + SDRC_MR_1)
+#define SDRC_EMR2_1_P (OMAP343X_SDRC_BASE + SDRC_EMR2_1)
+#define SDRC_MANUAL_1_P (OMAP343X_SDRC_BASE + SDRC_MANUAL_1)
+#define SDRC_DLLA_STATUS_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
+#define SDRC_DLLA_CTRL_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
.text
/* Function call to get the restore pointer for resume from OFF */
@@ -51,7 +64,93 @@ ENTRY(get_restore_pointer)
adr r0, restore
ldmfd sp!, {pc} @ restore regs and return
ENTRY(get_restore_pointer_sz)
- .word . - get_restore_pointer_sz
+ .word . - get_restore_pointer
+
+ .text
+/* Function call to get the restore pointer for for ES3 to resume from OFF */
+ENTRY(get_es3_restore_pointer)
+ stmfd sp!, {lr} @ save registers on stack
+ adr r0, restore_es3
+ ldmfd sp!, {pc} @ restore regs and return
+ENTRY(get_es3_restore_pointer_sz)
+ .word . - get_es3_restore_pointer
+
+ENTRY(es3_sdrc_fix)
+ ldr r4, sdrc_syscfg @ get config addr
+ ldr r5, [r4] @ get value
+ tst r5, #0x100 @ is part access blocked
+ it eq
+ biceq r5, r5, #0x100 @ clear bit if set
+ str r5, [r4] @ write back change
+ ldr r4, sdrc_mr_0 @ get config addr
+ ldr r5, [r4] @ get value
+ str r5, [r4] @ write back change
+ ldr r4, sdrc_emr2_0 @ get config addr
+ ldr r5, [r4] @ get value
+ str r5, [r4] @ write back change
+ ldr r4, sdrc_manual_0 @ get config addr
+ mov r5, #0x2 @ autorefresh command
+ str r5, [r4] @ kick off refreshes
+ ldr r4, sdrc_mr_1 @ get config addr
+ ldr r5, [r4] @ get value
+ str r5, [r4] @ write back change
+ ldr r4, sdrc_emr2_1 @ get config addr
+ ldr r5, [r4] @ get value
+ str r5, [r4] @ write back change
+ ldr r4, sdrc_manual_1 @ get config addr
+ mov r5, #0x2 @ autorefresh command
+ str r5, [r4] @ kick off refreshes
+ bx lr
+sdrc_syscfg:
+ .word SDRC_SYSCONFIG_P
+sdrc_mr_0:
+ .word SDRC_MR_0_P
+sdrc_emr2_0:
+ .word SDRC_EMR2_0_P
+sdrc_manual_0:
+ .word SDRC_MANUAL_0_P
+sdrc_mr_1:
+ .word SDRC_MR_1_P
+sdrc_emr2_1:
+ .word SDRC_EMR2_1_P
+sdrc_manual_1:
+ .word SDRC_MANUAL_1_P
+ENTRY(es3_sdrc_fix_sz)
+ .word . - es3_sdrc_fix
+
+/* Function to call rom code to save secure ram context */
+ENTRY(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
+ adr r3, api_params @ r3 points to parameters
+ str r0, [r3,#0x4] @ r0 has sdram address
+ ldr r12, high_mask
+ and r3, r3, r12
+ ldr r12, sram_phy_addr_mask
+ orr r3, r3, r12
+ mov r0, #25 @ set service ID for PPA
+ mov r12, r0 @ copy secure service ID in r12
+ mov r1, #0 @ set task id for ROM code in r1
+ mov r2, #4 @ set some flags in r2, r6
+ mov r6, #0xff
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5 @ data memory barrier
+ .word 0xE1600071 @ call SMI monitor (smi #1)
+ nop
+ nop
+ nop
+ nop
+ ldmfd sp!, {r1-r12, pc}
+sram_phy_addr_mask:
+ .word SRAM_BASE_P
+high_mask:
+ .word 0xffff
+api_params:
+ .word 0x4, 0x0, 0x0, 0x1, 0x1
+ENTRY(save_secure_ram_context_sz)
+ .word . - save_secure_ram_context
+
/*
* Forces OMAP into idle state
*
@@ -92,11 +191,29 @@ loop:
nop
nop
nop
- bl i_dll_wait
+ bl wait_sdrc_ok
ldmfd sp!, {r0-r12, pc} @ restore regs and return
+restore_es3:
+ /*b restore_es3*/ @ Enable to debug restore code
+ ldr r5, pm_prepwstst_core_p
+ ldr r4, [r5]
+ and r4, r4, #0x3
+ cmp r4, #0x0 @ Check if previous power state of CORE is OFF
+ bne restore
+ adr r0, es3_sdrc_fix
+ ldr r1, sram_base
+ ldr r2, es3_sdrc_fix_sz
+ mov r2, r2, ror #2
+copy_to_sram:
+ ldmia r0!, {r3} @ val = *src
+ stmia r1!, {r3} @ *dst = val
+ subs r2, r2, #0x1 @ num_words--
+ bne copy_to_sram
+ ldr r1, sram_base
+ blx r1
restore:
- /* b restore*/ @ Enable to debug restore code
+ /* b restore*/ @ Enable to debug restore code
/* Check what was the reason for mpu reset and store the reason in r9*/
/* 1 - Only L1 and logic lost */
/* 2 - Only L2 lost - In this case, we wont be here */
@@ -108,9 +225,44 @@ restore:
moveq r9, #0x3 @ MPU OFF => L1 and L2 lost
movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation
bne logic_l1_restore
+ ldr r0, control_stat
+ ldr r1, [r0]
+ and r1, #0x700
+ cmp r1, #0x300
+ beq l2_inv_gp
+ mov r0, #40 @ set service ID for PPA
+ mov r12, r0 @ copy secure Service ID in r12
+ mov r1, #0 @ set task id for ROM code in r1
+ mov r2, #4 @ set some flags in r2, r6
+ mov r6, #0xff
+ adr r3, l2_inv_api_params @ r3 points to dummy parameters
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5 @ data memory barrier
+ .word 0xE1600071 @ call SMI monitor (smi #1)
+ /* Write to Aux control register to set some bits */
+ mov r0, #42 @ set service ID for PPA
+ mov r12, r0 @ copy secure Service ID in r12
+ mov r1, #0 @ set task id for ROM code in r1
+ mov r2, #4 @ set some flags in r2, r6
+ mov r6, #0xff
+ adr r3, write_aux_control_params @ r3 points to parameters
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c10, 5 @ data memory barrier
+ .word 0xE1600071 @ call SMI monitor (smi #1)
+
+ b logic_l1_restore
+l2_inv_api_params:
+ .word 0x1, 0x00
+write_aux_control_params:
+ .word 0x1, 0x72
+l2_inv_gp:
/* Execute smi to invalidate L2 cache */
mov r12, #0x1 @ set up to invalide L2
-smi: .word 0xE1600070 @ Call SMI monitor (smieq)
+smi: .word 0xE1600070 @ Call SMI monitor (smieq)
+ /* Write to Aux control register to set some bits */
+ mov r0, #0x72
+ mov r12, #0x3
+ .word 0xE1600070 @ Call SMI monitor (smieq)
logic_l1_restore:
mov r1, #0
/* Invalidate all instruction caches to PoU
@@ -391,33 +543,55 @@ skip_l2_inval:
nop
nop
nop
- bl i_dll_wait
+ bl wait_sdrc_ok
/* restore regs and return */
ldmfd sp!, {r0-r12, pc}
-i_dll_wait:
- ldr r4, clk_stabilize_delay
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+ ldr r4, cm_idlest1_core
+ ldr r5, [r4]
+ and r5, r5, #0x2
+ cmp r5, #0
+ bne wait_sdrc_ok
+ ldr r4, sdrc_power
+ ldr r5, [r4]
+ bic r5, r5, #0x40
+ str r5, [r4]
+wait_dll_lock:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+ ldr r5, [r4]
+ tst r5, #0x4
+ bxne lr
+ /* wait till dll locks */
+ ldr r4, sdrc_dlla_status
+ ldr r5, [r4]
+ and r5, r5, #0x4
+ cmp r5, #0x4
+ bne wait_dll_lock
+ bx lr
-i_dll_delay:
- subs r4, r4, #0x1
- bne i_dll_delay
- ldr r4, sdrc_power
- ldr r5, [r4]
- bic r5, r5, #0x40
- str r5, [r4]
- bx lr
+cm_idlest1_core:
+ .word CM_IDLEST1_CORE_V
+sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
pm_prepwstst_core:
.word PM_PREPWSTST_CORE_V
+pm_prepwstst_core_p:
+ .word PM_PREPWSTST_CORE_P
pm_prepwstst_mpu:
.word PM_PREPWSTST_MPU_V
pm_pwstctrl_mpu:
.word PM_PWSTCTRL_MPU_P
scratchpad_base:
.word SCRATCHPAD_BASE_P
+sram_base:
+ .word SRAM_BASE_P + 0x8000
sdrc_power:
.word SDRC_POWER_V
-context_mem:
- .word 0x803E3E14
clk_stabilize_delay:
.word 0x000001FF
assoc_mask:
@@ -432,5 +606,7 @@ table_entry:
.word 0x00000C02
cache_pred_disable_mask:
.word 0xFFFFE7FB
+control_stat:
+ .word CONTROL_STAT
ENTRY(omap34xx_cpu_suspend_sz)
.word . - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index df2b7094de98..cd04deaa88c5 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -47,6 +47,7 @@ static struct omap_dm_timer *gptimer;
static struct clock_event_device clockevent_gpt;
static u8 __initdata gptimer_id = 1;
static u8 __initdata inited;
+struct omap_dm_timer *gptimer_wakeup;
static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
{
@@ -134,6 +135,7 @@ static void __init omap2_gp_clockevent_init(void)
gptimer = omap_dm_timer_request_specific(gptimer_id);
BUG_ON(gptimer == NULL);
+ gptimer_wakeup = gptimer;
#if defined(CONFIG_OMAP_32K_TIMER)
src = OMAP_TIMER_SRC_32_KHZ;
OpenPOWER on IntegriCloud