public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/13] OMAP2/3: PM sync-up
@ 2009-05-20 23:19 Kevin Hilman
  2009-05-20 23:19 ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kevin Hilman
  2009-05-26 23:12 ` [PATCH v2 00/13] OMAP2/3: PM sync-up Tony Lindgren
  0 siblings, 2 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

This series is intended to push the core PM support from linux-omap
into mainline.  

Upon review/acceptance, Tony will merge into his for-next branch for
the next merge window so all OMAP stuff can come from one place.

In addition to the linux-omap PM core sync, several OMAP3 init fixes
are required to ensure that the chip can hit full-chip retention on
idle and suspend.

Currently based on Tony's omap3-upstream branch.  Compile tested on
OMAP2, Boot tested on OMAP3430SDP and can hit full-chip retention in
suspend and in idle.

Changes since v1:
 - updated "push core PM" patch with review comments
   - dropped all /sys/power/* knobs
   - will use hlt_counter when it's exported to platform code
   - dropped save/restore of abort mode regs in favor of cpu_init()
 - MUSB idle patch fixed to work even when MUSB not enabled in Kconfig
 - 2 new patches
   - added UART-specific timeout feature under uart platform device.
     this replaces the need for /sys/power/clocks_off_while_idle   
   - revert of irq_chip->disable patch which is the wrong solution
     for the bug it was trying to fix

Jouni Hogander (2):
  OMAP: Add new function to check wether there is irq pending
  OMAP: UART: Add sysfs interface for adjusting UART sleep timeout

Kevin Hilman (10):
  Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  OMAP2/3: PM: push core PM code from linux-omap
  OMAP3: PM: Force IVA2 into idle during bootup
  OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X
  OMAP3: PM: UART: disable clocks when idle and off-mode support
  OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init
  OMAP3: PM: D2D clockdomain supports SW supervised transitions
  OMAP3: PM: Ensure PRCM interrupts are cleared at boot
  OMAP3: PM: Clear pending PRCM reset flags on init
  OMAP3: PM: prevent module wakeups from waking IVA2

Peter 'p2' De Schrijver (1):
  OMAP3: PM: Ensure MUSB block can idle when driver not loaded

 arch/arm/mach-omap2/Makefile              |    5 +-
 arch/arm/mach-omap2/clock34xx.c           |    3 +
 arch/arm/mach-omap2/clock34xx.h           |   33 ++-
 arch/arm/mach-omap2/clockdomains.h        |    2 +-
 arch/arm/mach-omap2/cm-regbits-34xx.h     |   14 +
 arch/arm/mach-omap2/irq.c                 |   18 +-
 arch/arm/mach-omap2/pm-debug.c            |  152 ++++++
 arch/arm/mach-omap2/pm.c                  |  134 +++----
 arch/arm/mach-omap2/pm.h                  |   40 ++
 arch/arm/mach-omap2/pm24xx.c              |  549 ++++++++++++++++++++++
 arch/arm/mach-omap2/pm34xx.c              |  710 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prcm-common.h         |    2 +
 arch/arm/mach-omap2/prm.h                 |    2 +
 arch/arm/mach-omap2/sdrc.c                |    5 +-
 arch/arm/mach-omap2/serial.c              |  437 +++++++++++++++++-
 arch/arm/mach-omap2/sleep24xx.S           |    1 -
 arch/arm/mach-omap2/sleep34xx.S           |  436 ++++++++++++++++++
 arch/arm/mach-omap2/usb-musb.c            |   21 +-
 arch/arm/plat-omap/Kconfig                |    2 +-
 arch/arm/plat-omap/common.c               |    1 -
 arch/arm/plat-omap/include/mach/common.h  |    2 -
 arch/arm/plat-omap/include/mach/control.h |   13 +
 arch/arm/plat-omap/include/mach/irqs.h    |    1 +
 arch/arm/plat-omap/include/mach/pm.h      |  345 --------------
 arch/arm/plat-omap/include/mach/serial.h  |    9 +
 arch/arm/plat-omap/include/mach/usb.h     |    6 -
 drivers/mtd/onenand/omap2.c               |    1 -
 27 files changed, 2475 insertions(+), 469 deletions(-)
 create mode 100644 arch/arm/mach-omap2/pm-debug.c
 create mode 100644 arch/arm/mach-omap2/pm.h
 create mode 100644 arch/arm/mach-omap2/pm24xx.c
 create mode 100644 arch/arm/mach-omap2/pm34xx.c
 create mode 100644 arch/arm/mach-omap2/sleep34xx.S
 delete mode 100644 arch/arm/plat-omap/include/mach/pm.h


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-20 23:19 [PATCH v2 00/13] OMAP2/3: PM sync-up Kevin Hilman
@ 2009-05-20 23:19 ` Kevin Hilman
  2009-05-20 23:19   ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Kevin Hilman
  2009-05-21 23:38   ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kim Kyuwon
  2009-05-26 23:12 ` [PATCH v2 00/13] OMAP2/3: PM sync-up Tony Lindgren
  1 sibling, 2 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.

Adding a disable hook to the irq_chip is not the way to fix the
problem being addressed by this patch.  Instead, we need to fix
support for [enable|disable]_irq_wake().

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/irq.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 998c5c4..08a3b99 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -134,7 +134,6 @@ static struct irq_chip omap_irq_chip = {
 	.ack	= omap_mask_ack_irq,
 	.mask	= omap_mask_irq,
 	.unmask	= omap_unmask_irq,
-	.disable = omap_mask_irq,
 };
 
 static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap
  2009-05-20 23:19 ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kevin Hilman
@ 2009-05-20 23:19   ` Kevin Hilman
  2009-05-20 23:19     ` [PATCH 03/13] OMAP: Add new function to check wether there is irq pending Kevin Hilman
  2009-05-28 15:48     ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Russell King - ARM Linux
  2009-05-21 23:38   ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kim Kyuwon
  1 sibling, 2 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

This patch is to sync the core linux-omap PM code with mainline.  This
code has evolved and been used for a while the linux-omap tree, but
the attempt here is to finally get this into mainline.

Following this will be a series of patches from the 'PM branch' of the
linux-omap tree to add full PM hardware support from the linux-omap
tree.

Much of this PM core code was written by Jouni Hogander with
significant contributions from Paul Walmsley as well as many others
from Nokia, Texas Instruments and linux-omap community.

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Cc: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/Makefile         |    3 +
 arch/arm/mach-omap2/pm-debug.c       |  152 +++++++++
 arch/arm/mach-omap2/pm.c             |  134 ++++-----
 arch/arm/mach-omap2/pm.h             |   40 +++
 arch/arm/mach-omap2/pm24xx.c         |  548 ++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm34xx.c         |  606 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prcm-common.h    |    2 +
 arch/arm/mach-omap2/sdrc.c           |    5 +-
 arch/arm/mach-omap2/sleep24xx.S      |    1 -
 arch/arm/mach-omap2/sleep34xx.S      |  436 ++++++++++++++++++++++++
 arch/arm/mach-omap2/usb-musb.c       |    1 -
 arch/arm/plat-omap/Kconfig           |    2 +-
 arch/arm/plat-omap/common.c          |    1 -
 arch/arm/plat-omap/include/mach/pm.h |  345 -------------------
 drivers/mtd/onenand/omap2.c          |    1 -
 15 files changed, 1848 insertions(+), 429 deletions(-)
 create mode 100644 arch/arm/mach-omap2/pm-debug.c
 create mode 100644 arch/arm/mach-omap2/pm.h
 create mode 100644 arch/arm/mach-omap2/pm24xx.c
 create mode 100644 arch/arm/mach-omap2/pm34xx.c
 create mode 100644 arch/arm/mach-omap2/sleep34xx.S
 delete mode 100644 arch/arm/plat-omap/include/mach/pm.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index dd1c0c5..c8f1505 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -26,7 +26,10 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-y					+= pm.o
+obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP24XX)		+= sleep24xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o
+obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 endif
 
 # Clock framework
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
new file mode 100644
index 0000000..6cc375a
--- /dev/null
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -0,0 +1,152 @@
+/*
+ * OMAP Power Management debug routines
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.com>
+ * Jouni Hogander
+ *
+ * Based on pm.c for omap2
+ *
+ * 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/kernel.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/clock.h>
+#include <mach/board.h>
+
+#include "prm.h"
+#include "cm.h"
+#include "pm.h"
+
+int omap2_pm_debug;
+
+#define DUMP_PRM_MOD_REG(mod, reg)    \
+	regs[reg_count].name = #mod "." #reg; \
+	regs[reg_count++].val = prm_read_mod_reg(mod, reg)
+#define DUMP_CM_MOD_REG(mod, reg)     \
+	regs[reg_count].name = #mod "." #reg; \
+	regs[reg_count++].val = cm_read_mod_reg(mod, reg)
+#define DUMP_PRM_REG(reg) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(reg)
+#define DUMP_CM_REG(reg) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(reg)
+#define DUMP_INTC_REG(reg, off) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
+
+void omap2_pm_dump(int mode, int resume, unsigned int us)
+{
+	struct reg {
+		const char *name;
+		u32 val;
+	} regs[32];
+	int reg_count = 0, i;
+	const char *s1 = NULL, *s2 = NULL;
+
+	if (!resume) {
+#if 0
+		/* MPU */
+		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
+		DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
+#endif
+#if 0
+		/* INTC */
+		DUMP_INTC_REG(INTC_MIR0, 0x0084);
+		DUMP_INTC_REG(INTC_MIR1, 0x00a4);
+		DUMP_INTC_REG(INTC_MIR2, 0x00c4);
+#endif
+#if 0
+		DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
+		if (cpu_is_omap24xx()) {
+			DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
+					OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
+			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
+					OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
+		}
+		DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
+		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
+		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
+		DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
+		DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
+		DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
+		DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
+#endif
+#if 0
+		/* DSP */
+		if (cpu_is_omap24xx()) {
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
+		}
+#endif
+	} else {
+		DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
+		if (cpu_is_omap24xx())
+			DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
+		DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
+		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+#if 1
+		DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
+		DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
+		DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
+#endif
+	}
+
+	switch (mode) {
+	case 0:
+		s1 = "full";
+		s2 = "retention";
+		break;
+	case 1:
+		s1 = "MPU";
+		s2 = "retention";
+		break;
+	case 2:
+		s1 = "MPU";
+		s2 = "idle";
+		break;
+	}
+
+	if (!resume)
+#ifdef CONFIG_NO_HZ
+		printk(KERN_INFO
+		       "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
+		       jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
+					jiffies));
+#else
+		printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
+#endif
+	else
+		printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
+			us / 1000, us % 1000);
+
+	for (i = 0; i < reg_count; i++)
+		printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
+}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index ea8ceae..dad2eef 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -1,13 +1,16 @@
 /*
- * linux/arch/arm/mach-omap2/pm.c
- *
- * OMAP2 Power Management Routines
- *
- * Copyright (C) 2006 Nokia Corporation
- * Tony Lindgren <tony@atomide.com>
+ * OMAP2/3 Power Management Common Routines
  *
  * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
  * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.com>
+ * Jouni Hogander
  *
  * Based on pm.c for omap1
  *
@@ -17,95 +20,70 @@
  */
 
 #include <linux/suspend.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/time.h>
 
-#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <mach/cpu.h>
 #include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-
-#include <mach/irqs.h>
-#include <mach/clock.h>
-#include <mach/sram.h>
-#include <mach/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);
-
-extern void __init pmdomain_init(void);
-extern void pmdomain_set_autoidle(void);
+#include <asm/atomic.h>
 
-static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
+#include "pm.h"
 
-void omap2_pm_idle(void)
-{
-	local_irq_disable();
-	local_fiq_disable();
-	if (need_resched()) {
-		local_fiq_enable();
-		local_irq_enable();
-		return;
-	}
+unsigned short enable_dyn_sleep;
 
-	omap2_sram_idle();
-	local_fiq_enable();
-	local_irq_enable();
-}
+static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *);
+static ssize_t idle_store(struct kobject *k, struct kobj_attribute *,
+			  const char *buf, size_t n);
 
-static int omap2_pm_prepare(void)
-{
-	/* We cannot sleep in idle until we have resumed */
-	saved_idle = pm_idle;
-	pm_idle = NULL;
-	return 0;
-}
+static struct kobj_attribute sleep_while_idle_attr =
+	__ATTR(sleep_while_idle, 0644, idle_show, idle_store);
 
-static int omap2_pm_suspend(void)
+static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
 {
-	return 0;
+	if (attr == &sleep_while_idle_attr)
+		return sprintf(buf, "%hu\n", enable_dyn_sleep);
+	else
+		return -EINVAL;
 }
 
-static int omap2_pm_enter(suspend_state_t state)
+static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
+			  const char *buf, size_t n)
 {
-	int ret = 0;
+	unsigned short value;
 
-	switch (state)
-	{
-	case PM_SUSPEND_STANDBY:
-	case PM_SUSPEND_MEM:
-		ret = omap2_pm_suspend();
-		break;
-	default:
-		ret = -EINVAL;
+	if (sscanf(buf, "%hu", &value) != 1 ||
+	    (value != 0 && value != 1)) {
+		printk(KERN_ERR "idle_store: Invalid value\n");
+		return -EINVAL;
 	}
 
-	return ret;
-}
+	if (attr == &sleep_while_idle_attr)
+		enable_dyn_sleep = value;
+	else
+		return -EINVAL;
 
-static void omap2_pm_finish(void)
-{
-	pm_idle = saved_idle;
+	return n;
 }
 
-static struct platform_suspend_ops omap_pm_ops = {
-	.prepare	= omap2_pm_prepare,
-	.enter		= omap2_pm_enter,
-	.finish		= omap2_pm_finish,
-	.valid		= suspend_valid_only_mem,
-};
-
-static int __init omap2_pm_init(void)
+static int __init omap_pm_init(void)
 {
-	return 0;
+	int error = -1;
+
+	if (cpu_is_omap24xx())
+		error = omap2_pm_init();
+	if (cpu_is_omap34xx())
+		error = omap3_pm_init();
+	if (error) {
+		printk(KERN_ERR "omap2|3_pm_init failed: %d\n", error);
+		return error;
+	}
+
+	/* disabled till drivers are fixed */
+	enable_dyn_sleep = 0;
+	error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
+	if (error)
+		printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
+	return error;
 }
 
-__initcall(omap2_pm_init);
+late_initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
new file mode 100644
index 0000000..784027b
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.h
@@ -0,0 +1,40 @@
+/*
+ * OMAP2/3 Power Management Routines
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Jouni Hogander
+ *
+ * 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.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PM_H
+#define __ARCH_ARM_MACH_OMAP2_PM_H
+
+extern int omap2_pm_init(void);
+extern int omap3_pm_init(void);
+
+extern unsigned short enable_dyn_sleep;
+
+#ifdef CONFIG_PM_DEBUG
+extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern int omap2_pm_debug;
+#else
+#define omap2_pm_dump(mode, resume, us)		do {} while (0);
+#define omap2_pm_debug				0
+#endif /* CONFIG_PM_DEBUG */
+
+extern void omap24xx_idle_loop_suspend(void);
+
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
+					void __iomem *sdrc_power);
+extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void save_secure_ram_context(u32 *addr);
+
+extern unsigned int omap24xx_idle_loop_suspend_sz;
+extern unsigned int omap34xx_suspend_sz;
+extern unsigned int save_secure_ram_context_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap34xx_cpu_suspend_sz;
+
+#endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
new file mode 100644
index 0000000..384a5b5
--- /dev/null
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -0,0 +1,548 @@
+/*
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.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/suspend.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/irqs.h>
+#include <mach/clock.h>
+#include <mach/sram.h>
+#include <mach/control.h>
+#include <mach/mux.h>
+#include <mach/dma.h>
+#include <mach/board.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "cm.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "pm.h"
+
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
+
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
+				  void __iomem *sdrc_power);
+static void (*saved_idle)(void);
+
+static struct powerdomain *mpu_pwrdm;
+static struct powerdomain *core_pwrdm;
+
+static struct clockdomain *dsp_clkdm;
+static struct clockdomain *gfx_clkdm;
+
+static struct clk *osc_ck, *emul_ck;
+
+static int omap2_fclks_active(void)
+{
+	u32 f1, f2;
+
+	f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	if (f1 | f2)
+		return 1;
+	return 0;
+}
+
+static int omap2_irq_pending(void)
+{
+	u32 pending_reg = 0x480fe098;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (omap_readl(pending_reg))
+			return 1;
+		pending_reg += 0x20;
+	}
+	return 0;
+}
+
+static void omap2_enter_full_retention(void)
+{
+	u32 l;
+	struct timespec ts_preidle, ts_postidle, ts_idle;
+
+	/* There is 1 reference hold for all children of the oscillator
+	 * clock, the following will remove it. If no one else uses the
+	 * oscillator itself it will be disabled if/when we enter retention
+	 * mode.
+	 */
+	clk_disable(osc_ck);
+
+	/* Clear old wake-up events */
+	/* REVISIT: These write to reserved bits? */
+	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+
+	/*
+	 * Set MPU powerdomain's next power state to RETENTION;
+	 * preserve logic state during retention
+	 */
+	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
+	/* Workaround to kill USB */
+	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
+	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
+
+	omap2_gpio_prepare_for_retention();
+
+	if (omap2_pm_debug) {
+		omap2_pm_dump(0, 0, 0);
+		getnstimeofday(&ts_preidle);
+	}
+
+	/* One last check for pending IRQs to avoid extra latency due
+	 * to sleeping unnecessarily. */
+	if (omap2_irq_pending())
+		goto no_sleep;
+
+	/* Jump to SRAM suspend code */
+	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
+			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
+			   OMAP_SDRC_REGADDR(SDRC_POWER));
+no_sleep:
+
+	if (omap2_pm_debug) {
+		unsigned long long tmp;
+
+		getnstimeofday(&ts_postidle);
+		ts_idle = timespec_sub(ts_postidle, ts_preidle);
+		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+		omap2_pm_dump(0, 1, tmp);
+	}
+	omap2_gpio_resume_after_retention();
+
+	clk_enable(osc_ck);
+
+	/* clear CORE wake-up events */
+	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+
+	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
+	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+
+	/* MPU domain wake events */
+	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	if (l & 0x01)
+		prm_write_mod_reg(0x01, OCP_MOD,
+				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	if (l & 0x20)
+		prm_write_mod_reg(0x20, OCP_MOD,
+				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+
+	/* Mask future PRCM-to-MPU interrupts */
+	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+}
+
+static int omap2_i2c_active(void)
+{
+	u32 l;
+
+	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	return l & (OMAP2420_EN_I2C2 | OMAP2420_EN_I2C1);
+}
+
+static int sti_console_enabled;
+
+static int omap2_allow_mpu_retention(void)
+{
+	u32 l;
+
+	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
+	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	if (l & (OMAP2420_EN_MMC | OMAP24XX_EN_UART2 |
+		 OMAP24XX_EN_UART1 | OMAP24XX_EN_MCSPI2 |
+		 OMAP24XX_EN_MCSPI1 | OMAP24XX_EN_DSS1))
+		return 0;
+	/* Check for UART3. */
+	l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	if (l & OMAP24XX_EN_UART3)
+		return 0;
+	if (sti_console_enabled)
+		return 0;
+
+	return 1;
+}
+
+static void omap2_enter_mpu_retention(void)
+{
+	int only_idle = 0;
+	struct timespec ts_preidle, ts_postidle, ts_idle;
+
+	/* Putting MPU into the WFI state while a transfer is active
+	 * seems to cause the I2C block to timeout. Why? Good question. */
+	if (omap2_i2c_active())
+		return;
+
+	/* The peripherals seem not to be able to wake up the MPU when
+	 * it is in retention mode. */
+	if (omap2_allow_mpu_retention()) {
+		/* REVISIT: These write to reserved bits? */
+		prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+		prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+		prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+
+		/* Try to enter MPU retention */
+		prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
+				  OMAP_LOGICRETSTATE,
+				  MPU_MOD, PM_PWSTCTRL);
+	} else {
+		/* Block MPU retention */
+
+		prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
+		only_idle = 1;
+	}
+
+	if (omap2_pm_debug) {
+		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
+		getnstimeofday(&ts_preidle);
+	}
+
+	omap2_sram_idle();
+
+	if (omap2_pm_debug) {
+		unsigned long long tmp;
+
+		getnstimeofday(&ts_postidle);
+		ts_idle = timespec_sub(ts_postidle, ts_preidle);
+		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
+	}
+}
+
+static int omap2_can_sleep(void)
+{
+	if (!enable_dyn_sleep)
+		return 0;
+	if (omap2_fclks_active())
+		return 0;
+	if (osc_ck->usecount > 1)
+		return 0;
+	if (omap_dma_running())
+		return 0;
+
+	return 1;
+}
+
+static void omap2_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+
+	if (!omap2_can_sleep()) {
+		if (omap2_irq_pending())
+			goto out;
+		omap2_enter_mpu_retention();
+		goto out;
+	}
+
+	if (omap2_irq_pending())
+		goto out;
+
+	omap2_enter_full_retention();
+
+out:
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int omap2_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+
+	return 0;
+}
+
+static int omap2_pm_suspend(void)
+{
+	u32 wken_wkup, mir1;
+
+	wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+	prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN);
+
+	/* Mask GPT1 */
+	mir1 = omap_readl(0x480fe0a4);
+	omap_writel(1 << 5, 0x480fe0ac);
+
+	omap2_enter_full_retention();
+
+	omap_writel(mir1, 0x480fe0a4);
+	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
+
+	return 0;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = omap2_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void omap2_pm_finish(void)
+{
+	pm_idle = saved_idle;
+}
+
+static struct platform_suspend_ops omap_pm_ops = {
+	.prepare	= omap2_pm_prepare,
+	.enter		= omap2_pm_enter,
+	.finish		= omap2_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
+{
+	omap2_clkdm_allow_idle(clkdm);
+	return 0;
+}
+
+static void __init prcm_setup_regs(void)
+{
+	int i, num_mem_banks;
+	struct powerdomain *pwrdm;
+
+	/* Enable autoidle */
+	prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
+			  OMAP2_PRCM_SYSCONFIG_OFFSET);
+
+	/* Set all domain wakeup dependencies */
+	prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
+	if (cpu_is_omap2430())
+		prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
+
+	/*
+	 * Set CORE powerdomain memory banks to retain their contents
+	 * during RETENTION
+	 */
+	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
+	for (i = 0; i < num_mem_banks; i++)
+		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+
+	/* Set CORE powerdomain's next power state to RETENTION */
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+
+	/*
+	 * Set MPU powerdomain's next power state to RETENTION;
+	 * preserve logic state during retention
+	 */
+	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
+	/* Force-power down DSP, GFX powerdomains */
+
+	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
+	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap2_clkdm_sleep(dsp_clkdm);
+
+	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
+	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap2_clkdm_sleep(gfx_clkdm);
+
+	/* Enable clockdomain hardware-supervised control for all clkdms */
+	clkdm_for_each(_pm_clkdm_enable_hwsup);
+
+	/* Enable clock autoidle for all domains */
+	cm_write_mod_reg(OMAP24XX_AUTO_CAM |
+			 OMAP24XX_AUTO_MAILBOXES |
+			 OMAP24XX_AUTO_WDT4 |
+			 OMAP2420_AUTO_WDT3 |
+			 OMAP24XX_AUTO_MSPRO |
+			 OMAP2420_AUTO_MMC |
+			 OMAP24XX_AUTO_FAC |
+			 OMAP2420_AUTO_EAC |
+			 OMAP24XX_AUTO_HDQ |
+			 OMAP24XX_AUTO_UART2 |
+			 OMAP24XX_AUTO_UART1 |
+			 OMAP24XX_AUTO_I2C2 |
+			 OMAP24XX_AUTO_I2C1 |
+			 OMAP24XX_AUTO_MCSPI2 |
+			 OMAP24XX_AUTO_MCSPI1 |
+			 OMAP24XX_AUTO_MCBSP2 |
+			 OMAP24XX_AUTO_MCBSP1 |
+			 OMAP24XX_AUTO_GPT12 |
+			 OMAP24XX_AUTO_GPT11 |
+			 OMAP24XX_AUTO_GPT10 |
+			 OMAP24XX_AUTO_GPT9 |
+			 OMAP24XX_AUTO_GPT8 |
+			 OMAP24XX_AUTO_GPT7 |
+			 OMAP24XX_AUTO_GPT6 |
+			 OMAP24XX_AUTO_GPT5 |
+			 OMAP24XX_AUTO_GPT4 |
+			 OMAP24XX_AUTO_GPT3 |
+			 OMAP24XX_AUTO_GPT2 |
+			 OMAP2420_AUTO_VLYNQ |
+			 OMAP24XX_AUTO_DSS,
+			 CORE_MOD, CM_AUTOIDLE1);
+	cm_write_mod_reg(OMAP24XX_AUTO_UART3 |
+			 OMAP24XX_AUTO_SSI |
+			 OMAP24XX_AUTO_USB,
+			 CORE_MOD, CM_AUTOIDLE2);
+	cm_write_mod_reg(OMAP24XX_AUTO_SDRC |
+			 OMAP24XX_AUTO_GPMC |
+			 OMAP24XX_AUTO_SDMA,
+			 CORE_MOD, CM_AUTOIDLE3);
+	cm_write_mod_reg(OMAP24XX_AUTO_PKA |
+			 OMAP24XX_AUTO_AES |
+			 OMAP24XX_AUTO_RNG |
+			 OMAP24XX_AUTO_SHA |
+			 OMAP24XX_AUTO_DES,
+			 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
+
+	cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+
+	/* Put DPLL and both APLLs into autoidle mode */
+	cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
+			 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
+			 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
+			 PLL_MOD, CM_AUTOIDLE);
+
+	cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL |
+			 OMAP24XX_AUTO_WDT1 |
+			 OMAP24XX_AUTO_MPU_WDT |
+			 OMAP24XX_AUTO_GPIOS |
+			 OMAP24XX_AUTO_32KSYNC |
+			 OMAP24XX_AUTO_GPT1,
+			 WKUP_MOD, CM_AUTOIDLE);
+
+	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
+	 * stabilisation */
+	prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+			  OMAP2_PRCM_CLKSSETUP_OFFSET);
+
+	/* Configure automatic voltage transition */
+	prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+			  OMAP2_PRCM_VOLTSETUP_OFFSET);
+	prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT |
+			  (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
+			  OMAP24XX_MEMRETCTRL |
+			  (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
+			  (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
+			  OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
+
+	/* Enable wake-up events */
+	prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1,
+			  WKUP_MOD, PM_WKEN);
+}
+
+int __init omap2_pm_init(void)
+{
+	u32 l;
+
+	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
+	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
+	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+
+	/* Look up important powerdomains, clockdomains */
+
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+	if (!mpu_pwrdm)
+		pr_err("PM: mpu_pwrdm not found\n");
+
+	core_pwrdm = pwrdm_lookup("core_pwrdm");
+	if (!core_pwrdm)
+		pr_err("PM: core_pwrdm not found\n");
+
+	dsp_clkdm = clkdm_lookup("dsp_clkdm");
+	if (!dsp_clkdm)
+		pr_err("PM: mpu_clkdm not found\n");
+
+	gfx_clkdm = clkdm_lookup("gfx_clkdm");
+	if (!gfx_clkdm)
+		pr_err("PM: gfx_clkdm not found\n");
+
+
+	osc_ck = clk_get(NULL, "osc_ck");
+	if (IS_ERR(osc_ck)) {
+		printk(KERN_ERR "could not get osc_ck\n");
+		return -ENODEV;
+	}
+
+	if (cpu_is_omap242x()) {
+		emul_ck = clk_get(NULL, "emul_ck");
+		if (IS_ERR(emul_ck)) {
+			printk(KERN_ERR "could not get emul_ck\n");
+			clk_put(osc_ck);
+			return -ENODEV;
+		}
+	}
+
+	prcm_setup_regs();
+
+	/* Hack to prevent MPU retention when STI console is enabled. */
+	{
+		const struct omap_sti_console_config *sti;
+
+		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
+				      struct omap_sti_console_config);
+		if (sti != NULL && sti->enable)
+			sti_console_enabled = 1;
+	}
+
+	/*
+	 * 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.
+	 */
+	if (cpu_is_omap24xx()) {
+		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);
+	}
+
+	suspend_set_ops(&omap_pm_ops);
+	pm_idle = omap2_pm_idle;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
new file mode 100644
index 0000000..61ccaf3
--- /dev/null
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -0,0 +1,606 @@
+/*
+ * OMAP3 Power Management Routines
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Jouni Hogander
+ *
+ * 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/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+
+#include <mach/sram.h>
+#include <mach/clockdomain.h>
+#include <mach/powerdomain.h>
+#include <mach/control.h>
+
+#include "cm.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+#include "prm.h"
+#include "pm.h"
+
+struct power_state {
+	struct powerdomain *pwrdm;
+	u32 next_state;
+	u32 saved_state;
+	struct list_head node;
+};
+
+static LIST_HEAD(pwrst_list);
+
+static void (*_omap_sram_idle)(u32 *addr, int save_state);
+
+static void (*saved_idle)(void);
+
+static struct powerdomain *mpu_pwrdm;
+
+/* PRCM Interrupt Handler for wakeups */
+static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
+{
+	u32 wkst, irqstatus_mpu;
+	u32 fclk, iclk;
+
+	/* WKUP */
+	wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
+	if (wkst) {
+		iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
+		fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
+		cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN);
+		cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN);
+		prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST);
+		while (prm_read_mod_reg(WKUP_MOD, PM_WKST))
+			cpu_relax();
+		cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN);
+		cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN);
+	}
+
+	/* CORE */
+	wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
+	if (wkst) {
+		iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
+		fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1);
+		prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1);
+		while (prm_read_mod_reg(CORE_MOD, PM_WKST1))
+			cpu_relax();
+		cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1);
+		cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1);
+	}
+	wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
+	if (wkst) {
+		iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
+		fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+		prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3);
+		while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3))
+			cpu_relax();
+		cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3);
+		cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+	}
+
+	/* PER */
+	wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
+	if (wkst) {
+		iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
+		fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
+		cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN);
+		cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN);
+		prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST);
+		while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST))
+			cpu_relax();
+		cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN);
+		cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN);
+	}
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		/* USBHOST */
+		wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
+		if (wkst) {
+			iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					       CM_ICLKEN);
+			fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					       CM_FCLKEN);
+			cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
+					    CM_ICLKEN);
+			cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
+					    CM_FCLKEN);
+			prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD,
+					  PM_WKST);
+			while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+						PM_WKST))
+				cpu_relax();
+			cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD,
+					 CM_ICLKEN);
+			cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD,
+					 CM_FCLKEN);
+		}
+	}
+
+	irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
+					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
+			  OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET))
+		cpu_relax();
+
+	return IRQ_HANDLED;
+}
+
+static void omap_sram_idle(void)
+{
+	/* Variable to tell what needs to be saved and restored
+	 * in omap_sram_idle*/
+	/* save_state = 0 => Nothing to save and restored */
+	/* 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;
+
+	if (!_omap_sram_idle)
+		return;
+
+	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	switch (mpu_next_state) {
+	case PWRDM_POWER_RET:
+		/* No need to save context */
+		save_state = 0;
+		break;
+	default:
+		/* Invalid state */
+		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
+		return;
+	}
+	omap2_gpio_prepare_for_retention();
+
+	_omap_sram_idle(NULL, save_state);
+	cpu_init();
+
+	omap2_gpio_resume_after_retention();
+}
+
+/*
+ * Check if functional clocks are enabled before entering
+ * sleep. This function could be behind CONFIG_PM_DEBUG
+ * when all drivers are configuring their sysconfig registers
+ * properly and using their clocks properly.
+ */
+static int omap3_fclks_active(void)
+{
+	u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0,
+		fck_cam = 0, fck_per = 0, fck_usbhost = 0;
+
+	fck_core1 = cm_read_mod_reg(CORE_MOD,
+				    CM_FCLKEN1);
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		fck_core3 = cm_read_mod_reg(CORE_MOD,
+					    OMAP3430ES2_CM_FCLKEN3);
+		fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
+					  CM_FCLKEN);
+		fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					      CM_FCLKEN);
+	} else
+		fck_sgx = cm_read_mod_reg(GFX_MOD,
+					  OMAP3430ES2_CM_FCLKEN3);
+	fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD,
+				  CM_FCLKEN);
+	fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD,
+				  CM_FCLKEN);
+	fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
+				  CM_FCLKEN);
+	if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
+	    fck_cam | fck_per | fck_usbhost)
+		return 1;
+	return 0;
+}
+
+static int omap3_can_sleep(void)
+{
+	if (!enable_dyn_sleep)
+		return 0;
+	if (omap3_fclks_active())
+		return 0;
+	return 1;
+}
+
+/* This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled. */
+static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+	u32 cur_state;
+	int sleep_switch = 0;
+	int ret = 0;
+
+	if (pwrdm == NULL || IS_ERR(pwrdm))
+		return -EINVAL;
+
+	while (!(pwrdm->pwrsts & (1 << state))) {
+		if (state == PWRDM_POWER_OFF)
+			return ret;
+		state--;
+	}
+
+	cur_state = pwrdm_read_next_pwrst(pwrdm);
+	if (cur_state == state)
+		return ret;
+
+	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+		omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+		sleep_switch = 1;
+		pwrdm_wait_transition(pwrdm);
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, state);
+	if (ret) {
+		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+		       pwrdm->name);
+		goto err;
+	}
+
+	if (sleep_switch) {
+		omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		pwrdm_wait_transition(pwrdm);
+	}
+
+err:
+	return ret;
+}
+
+static void omap3_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+
+	if (!omap3_can_sleep())
+		goto out;
+
+	if (omap_irq_pending())
+		goto out;
+
+	omap_sram_idle();
+
+out:
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int omap3_pm_prepare(void)
+{
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+	return 0;
+}
+
+static int omap3_pm_suspend(void)
+{
+	struct power_state *pwrst;
+	int state, ret = 0;
+
+	/* Read current next_pwrsts */
+	list_for_each_entry(pwrst, &pwrst_list, node)
+		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+	/* Set ones wanted by suspend */
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+			goto restore;
+		if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
+			goto restore;
+	}
+
+	omap_sram_idle();
+
+restore:
+	/* Restore next_pwrsts */
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		if (state > pwrst->next_state) {
+			printk(KERN_INFO "Powerdomain (%s) didn't enter "
+			       "target state %d\n",
+			       pwrst->pwrdm->name, pwrst->next_state);
+			ret = -1;
+		}
+	}
+	if (ret)
+		printk(KERN_ERR "Could not enter target state in pm_suspend\n");
+	else
+		printk(KERN_INFO "Successfully put all powerdomains "
+		       "to target state\n");
+
+	return ret;
+}
+
+static int omap3_pm_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = omap3_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void omap3_pm_finish(void)
+{
+	pm_idle = saved_idle;
+}
+
+static struct platform_suspend_ops omap_pm_ops = {
+	.prepare	= omap3_pm_prepare,
+	.enter		= omap3_pm_enter,
+	.finish		= omap3_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static void __init prcm_setup_regs(void)
+{
+	/* reset modem */
+	prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
+			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
+			  CORE_MOD, RM_RSTCTRL);
+	prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
+
+	/* XXX Reset all wkdeps. This should be done when initializing
+	 * powerdomains */
+	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
+		prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
+	} else
+		prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
+
+	/*
+	 * Enable interface clock autoidle for all modules.
+	 * Note that in the long run this should be done by clockfw
+	 */
+	cm_write_mod_reg(
+		OMAP3430ES2_AUTO_MMC3 |
+		OMAP3430ES2_AUTO_ICR |
+		OMAP3430_AUTO_AES2 |
+		OMAP3430_AUTO_SHA12 |
+		OMAP3430_AUTO_DES2 |
+		OMAP3430_AUTO_MMC2 |
+		OMAP3430_AUTO_MMC1 |
+		OMAP3430_AUTO_MSPRO |
+		OMAP3430_AUTO_HDQ |
+		OMAP3430_AUTO_MCSPI4 |
+		OMAP3430_AUTO_MCSPI3 |
+		OMAP3430_AUTO_MCSPI2 |
+		OMAP3430_AUTO_MCSPI1 |
+		OMAP3430_AUTO_I2C3 |
+		OMAP3430_AUTO_I2C2 |
+		OMAP3430_AUTO_I2C1 |
+		OMAP3430_AUTO_UART2 |
+		OMAP3430_AUTO_UART1 |
+		OMAP3430_AUTO_GPT11 |
+		OMAP3430_AUTO_GPT10 |
+		OMAP3430_AUTO_MCBSP5 |
+		OMAP3430_AUTO_MCBSP1 |
+		OMAP3430ES1_AUTO_FAC | /* This is es1 only */
+		OMAP3430_AUTO_MAILBOXES |
+		OMAP3430_AUTO_OMAPCTRL |
+		OMAP3430ES1_AUTO_FSHOSTUSB |
+		OMAP3430_AUTO_HSOTGUSB |
+		OMAP3430ES1_AUTO_D2D | /* This is es1 only */
+		OMAP3430_AUTO_SSI,
+		CORE_MOD, CM_AUTOIDLE1);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_PKA |
+		OMAP3430_AUTO_AES1 |
+		OMAP3430_AUTO_RNG |
+		OMAP3430_AUTO_SHA11 |
+		OMAP3430_AUTO_DES1,
+		CORE_MOD, CM_AUTOIDLE2);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		cm_write_mod_reg(
+			OMAP3430ES2_AUTO_USBTLL,
+			CORE_MOD, CM_AUTOIDLE3);
+	}
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_WDT2 |
+		OMAP3430_AUTO_WDT1 |
+		OMAP3430_AUTO_GPIO1 |
+		OMAP3430_AUTO_32KSYNC |
+		OMAP3430_AUTO_GPT12 |
+		OMAP3430_AUTO_GPT1 ,
+		WKUP_MOD, CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_DSS,
+		OMAP3430_DSS_MOD,
+		CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_CAM,
+		OMAP3430_CAM_MOD,
+		CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_GPIO6 |
+		OMAP3430_AUTO_GPIO5 |
+		OMAP3430_AUTO_GPIO4 |
+		OMAP3430_AUTO_GPIO3 |
+		OMAP3430_AUTO_GPIO2 |
+		OMAP3430_AUTO_WDT3 |
+		OMAP3430_AUTO_UART3 |
+		OMAP3430_AUTO_GPT9 |
+		OMAP3430_AUTO_GPT8 |
+		OMAP3430_AUTO_GPT7 |
+		OMAP3430_AUTO_GPT6 |
+		OMAP3430_AUTO_GPT5 |
+		OMAP3430_AUTO_GPT4 |
+		OMAP3430_AUTO_GPT3 |
+		OMAP3430_AUTO_GPT2 |
+		OMAP3430_AUTO_MCBSP4 |
+		OMAP3430_AUTO_MCBSP3 |
+		OMAP3430_AUTO_MCBSP2,
+		OMAP3430_PER_MOD,
+		CM_AUTOIDLE);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		cm_write_mod_reg(
+			OMAP3430ES2_AUTO_USBHOST,
+			OMAP3430ES2_USBHOST_MOD,
+			CM_AUTOIDLE);
+	}
+
+	/*
+	 * Set all plls to autoidle. This is needed until autoidle is
+	 * enabled by clockfw
+	 */
+	cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
+			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
+	cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
+			 MPU_MOD,
+			 CM_AUTOIDLE2);
+	cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
+			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
+			 PLL_MOD,
+			 CM_AUTOIDLE);
+	cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
+			 PLL_MOD,
+			 CM_AUTOIDLE2);
+
+	/*
+	 * Enable control of expternal oscillator through
+	 * sys_clkreq. In the long run clock framework should
+	 * take care of this.
+	 */
+	prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
+			     1 << OMAP_AUTOEXTCLKMODE_SHIFT,
+			     OMAP3430_GR_MOD,
+			     OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+	/* setup wakup source */
+	prm_write_mod_reg(OMAP3430_EN_IO | OMAP3430_EN_GPIO1 |
+			  OMAP3430_EN_GPT1 | OMAP3430_EN_GPT12,
+			  WKUP_MOD, PM_WKEN);
+	/* No need to write EN_IO, that is always enabled */
+	prm_write_mod_reg(OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1 |
+			  OMAP3430_EN_GPT12,
+			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
+	/* For some reason IO doesn't generate wakeup event even if
+	 * it is selected to mpu wakeup goup */
+	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
+			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+}
+
+static int __init pwrdms_setup(struct powerdomain *pwrdm)
+{
+	struct power_state *pwrst;
+
+	if (!pwrdm->pwrsts)
+		return 0;
+
+	pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL);
+	if (!pwrst)
+		return -ENOMEM;
+	pwrst->pwrdm = pwrdm;
+	pwrst->next_state = PWRDM_POWER_RET;
+	list_add(&pwrst->node, &pwrst_list);
+
+	if (pwrdm_has_hdwr_sar(pwrdm))
+		pwrdm_enable_hdwr_sar(pwrdm);
+
+	return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+}
+
+/*
+ * Enable hw supervised mode for all clockdomains if it's
+ * supported. Initiate sleep transition for other clockdomains, if
+ * they are not used
+ */
+static int __init clkdms_setup(struct clockdomain *clkdm)
+{
+	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
+		omap2_clkdm_allow_idle(clkdm);
+	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
+		 atomic_read(&clkdm->usecount) == 0)
+		omap2_clkdm_sleep(clkdm);
+	return 0;
+}
+
+int __init omap3_pm_init(void)
+{
+	struct power_state *pwrst, *tmp;
+	int ret;
+
+	printk(KERN_ERR "Power Management for TI OMAP3.\n");
+
+	/* XXX prcm_setup_regs needs to be before enabling hw
+	 * supervised mode for powerdomains */
+	prcm_setup_regs();
+
+	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
+			  (irq_handler_t)prcm_interrupt_handler,
+			  IRQF_DISABLED, "prcm", NULL);
+	if (ret) {
+		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
+		       INT_34XX_PRCM_MPU_IRQ);
+		goto err1;
+	}
+
+	ret = pwrdm_for_each(pwrdms_setup);
+	if (ret) {
+		printk(KERN_ERR "Failed to setup powerdomains\n");
+		goto err2;
+	}
+
+	(void) clkdm_for_each(clkdms_setup);
+
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+	if (mpu_pwrdm == NULL) {
+		printk(KERN_ERR "Failed to get mpu_pwrdm\n");
+		goto err2;
+	}
+
+	_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
+					 omap34xx_cpu_suspend_sz);
+
+	suspend_set_ops(&omap_pm_ops);
+
+	pm_idle = omap3_pm_idle;
+
+err1:
+	return ret;
+err2:
+	free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+	list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
+		list_del(&pwrst->node);
+		kfree(pwrst);
+	}
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 812d50e..cb1ae84 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -276,6 +276,8 @@
 /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
 #define OMAP3430_EN_GPIO1				(1 << 3)
 #define OMAP3430_EN_GPIO1_SHIFT				3
+#define OMAP3430_EN_GPT12				(1 << 1)
+#define OMAP3430_EN_GPT12_SHIFT				1
 #define OMAP3430_EN_GPT1				(1 << 0)
 #define OMAP3430_EN_GPT1_SHIFT				0
 
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index 2a30060..993fd25 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -56,9 +56,12 @@ struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
 {
 	struct omap_sdrc_params *sp;
 
+	if (!sdrc_init_params)
+		return NULL;
+
 	sp = sdrc_init_params;
 
-	while (sp->rate != r)
+	while (sp->rate && sp->rate != r)
 		sp++;
 
 	if (!sp->rate)
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
index bf9e961..130aadb 100644
--- a/arch/arm/mach-omap2/sleep24xx.S
+++ b/arch/arm/mach-omap2/sleep24xx.S
@@ -28,7 +28,6 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <mach/pm.h>
 
 #include <mach/omap24xx.h>
 
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
new file mode 100644
index 0000000..e5e2553
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -0,0 +1,436 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2007
+ * Texas Instruments
+ * Karthik Dasu <karthik-dp@ti.com>
+ *
+ * (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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/io.h>
+#include <mach/control.h>
+
+#include "prm.h"
+#include "sdrc.h"
+
+#define PM_PREPWSTST_CORE_V	OMAP34XX_PRM_REGADDR(CORE_MOD, \
+				OMAP3430_PM_PREPWSTST)
+#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 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 SDRC_POWER_V		OMAP34XX_SDRC_REGADDR(SDRC_POWER)
+
+	.text
+/* Function call to get the restore pointer for resume from OFF */
+ENTRY(get_restore_pointer)
+        stmfd   sp!, {lr}     @ save registers on stack
+	adr	r0, restore
+        ldmfd   sp!, {pc}     @ restore regs and return
+ENTRY(get_restore_pointer_sz)
+        .word   . - get_restore_pointer_sz
+/*
+ * Forces OMAP into idle state
+ *
+ * omap34xx_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap34xx_cpu_suspend)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+loop:
+	/*b	loop*/	@Enable to debug by stepping through code
+	/* r0 contains restore pointer in sdram */
+	/* r1 contains information about saving context */
+	ldr     r4, sdrc_power          @ read the SDRC_POWER register
+	ldr     r5, [r4]                @ read the contents of SDRC_POWER
+	orr     r5, r5, #0x40           @ enable self refresh on idle req
+	str     r5, [r4]                @ write back to SDRC_POWER register
+
+	cmp	r1, #0x0
+	/* If context save is required, do that and execute wfi */
+	bne	save_context_wfi
+	/* Data memory barrier and Data sync barrier */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+
+	wfi				@ wait for interrupt
+
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bl i_dll_wait
+
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+restore:
+	/* 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 */
+        /* 3 - Both L1 and L2 lost */
+	ldr     r1, pm_pwstctrl_mpu
+	ldr	r2, [r1]
+	and     r2, r2, #0x3
+	cmp     r2, #0x0	@ Check if target power state was OFF or RET
+        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
+	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
+	bne	logic_l1_restore
+	/* Execute smi to invalidate L2 cache */
+	mov r12, #0x1                         @ set up to invalide L2
+smi:    .word 0xE1600070                @ Call SMI monitor (smieq)
+logic_l1_restore:
+	mov	r1, #0
+	/* Invalidate all instruction caches to PoU
+	 * and flush branch target cache */
+	mcr	p15, 0, r1, c7, c5, 0
+
+	ldr	r4, scratchpad_base
+	ldr	r3, [r4,#0xBC]
+	ldmia	r3!, {r4-r6}
+	mov	sp, r4
+	msr	spsr_cxsf, r5
+	mov	lr, r6
+
+	ldmia	r3!, {r4-r9}
+	/* Coprocessor access Control Register */
+	mcr p15, 0, r4, c1, c0, 2
+
+	/* TTBR0 */
+	MCR p15, 0, r5, c2, c0, 0
+	/* TTBR1 */
+	MCR p15, 0, r6, c2, c0, 1
+	/* Translation table base control register */
+	MCR p15, 0, r7, c2, c0, 2
+	/*domain access Control Register */
+	MCR p15, 0, r8, c3, c0, 0
+	/* data fault status Register */
+	MCR p15, 0, r9, c5, c0, 0
+
+	ldmia  r3!,{r4-r8}
+	/* instruction fault status Register */
+	MCR p15, 0, r4, c5, c0, 1
+	/*Data Auxiliary Fault Status Register */
+	MCR p15, 0, r5, c5, c1, 0
+	/*Instruction Auxiliary Fault Status Register*/
+	MCR p15, 0, r6, c5, c1, 1
+	/*Data Fault Address Register */
+	MCR p15, 0, r7, c6, c0, 0
+	/*Instruction Fault Address Register*/
+	MCR p15, 0, r8, c6, c0, 2
+	ldmia  r3!,{r4-r7}
+
+	/* user r/w thread and process ID */
+	MCR p15, 0, r4, c13, c0, 2
+	/* user ro thread and process ID */
+	MCR p15, 0, r5, c13, c0, 3
+	/*Privileged only thread and process ID */
+	MCR p15, 0, r6, c13, c0, 4
+	/* cache size selection */
+	MCR p15, 2, r7, c0, c0, 0
+	ldmia  r3!,{r4-r8}
+	/* Data TLB lockdown registers */
+	MCR p15, 0, r4, c10, c0, 0
+	/* Instruction TLB lockdown registers */
+	MCR p15, 0, r5, c10, c0, 1
+	/* Secure or Nonsecure Vector Base Address */
+	MCR p15, 0, r6, c12, c0, 0
+	/* FCSE PID */
+	MCR p15, 0, r7, c13, c0, 0
+	/* Context PID */
+	MCR p15, 0, r8, c13, c0, 1
+
+	ldmia  r3!,{r4-r5}
+	/* primary memory remap register */
+	MCR p15, 0, r4, c10, c2, 0
+	/*normal memory remap register */
+	MCR p15, 0, r5, c10, c2, 1
+
+	/* Restore cpsr */
+	ldmia	r3!,{r4}	/*load CPSR from SDRAM*/
+	msr	cpsr, r4	/*store cpsr */
+
+	/* Enabling MMU here */
+	mrc	p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
+	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
+	and	r7, #0x7
+	cmp	r7, #0x0
+	beq	usettbr0
+ttbr_error:
+	/* More work needs to be done to support N[0:2] value other than 0
+	* So looping here so that the error can be detected
+	*/
+	b	ttbr_error
+usettbr0:
+	mrc	p15, 0, r2, c2, c0, 0
+	ldr	r5, ttbrbit_mask
+	and	r2, r5
+	mov	r4, pc
+	ldr	r5, table_index_mask
+	and	r4, r5 /* r4 = 31 to 20 bits of pc */
+	/* Extract the value to be written to table entry */
+	ldr	r1, table_entry
+	add	r1, r1, r4 /* r1 has value to be written to table entry*/
+	/* Getting the address of table entry to modify */
+	lsr	r4, #18
+	add	r2, r4 /* r2 has the location which needs to be modified */
+	/* Storing previous entry of location being modified */
+	ldr	r5, scratchpad_base
+	ldr	r4, [r2]
+	str	r4, [r5, #0xC0]
+	/* Modify the table entry */
+	str	r1, [r2]
+	/* Storing address of entry being modified
+	 * - will be restored after enabling MMU */
+	ldr	r5, scratchpad_base
+	str	r2, [r5, #0xC4]
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
+	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
+	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
+	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
+	/* Restore control register  but dont enable caches here*/
+	/* Caches will be enabled after restoring MMU table entry */
+	ldmia	r3!, {r4}
+	/* Store previous value of control register in scratchpad */
+	str	r4, [r5, #0xC8]
+	ldr	r2, cache_pred_disable_mask
+	and	r4, r2
+	mcr	p15, 0, r4, c1, c0, 0
+
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+save_context_wfi:
+	/*b	save_context_wfi*/	@ enable to debug save code
+	mov	r8, r0 /* Store SDRAM address in r8 */
+        /* Check what that target sleep state is:stored in r1*/
+        /* 1 - Only L1 and logic lost */
+        /* 2 - Only L2 lost */
+        /* 3 - Both L1 and L2 lost */
+	cmp	r1, #0x2 /* Only L2 lost */
+	beq	clean_l2
+	cmp	r1, #0x1 /* L2 retained */
+	/* r9 stores whether to clean L2 or not*/
+	moveq	r9, #0x0 /* Dont Clean L2 */
+	movne	r9, #0x1 /* Clean L2 */
+l1_logic_lost:
+	/* Store sp and spsr to SDRAM */
+	mov	r4, sp
+	mrs	r5, spsr
+	mov	r6, lr
+	stmia	r8!, {r4-r6}
+	/* Save all ARM registers */
+	/* Coprocessor access control register */
+	mrc	p15, 0, r6, c1, c0, 2
+	stmia	r8!, {r6}
+	/* TTBR0, TTBR1 and Translation table base control */
+	mrc	p15, 0, r4, c2, c0, 0
+	mrc	p15, 0, r5, c2, c0, 1
+	mrc	p15, 0, r6, c2, c0, 2
+	stmia	r8!, {r4-r6}
+	/* Domain access control register, data fault status register,
+	and instruction fault status register */
+	mrc	p15, 0, r4, c3, c0, 0
+	mrc	p15, 0, r5, c5, c0, 0
+	mrc	p15, 0, r6, c5, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Data aux fault status register, instruction aux fault status,
+	datat fault address register and instruction fault address register*/
+	mrc	p15, 0, r4, c5, c1, 0
+	mrc	p15, 0, r5, c5, c1, 1
+	mrc	p15, 0, r6, c6, c0, 0
+	mrc	p15, 0, r7, c6, c0, 2
+	stmia	r8!, {r4-r7}
+	/* user r/w thread and process ID, user r/o thread and process ID,
+	priv only thread and process ID, cache size selection */
+	mrc	p15, 0, r4, c13, c0, 2
+	mrc	p15, 0, r5, c13, c0, 3
+	mrc	p15, 0, r6, c13, c0, 4
+	mrc	p15, 2, r7, c0, c0, 0
+	stmia	r8!, {r4-r7}
+	/* Data TLB lockdown, instruction TLB lockdown registers */
+	mrc	p15, 0, r5, c10, c0, 0
+	mrc	p15, 0, r6, c10, c0, 1
+	stmia	r8!, {r5-r6}
+	/* Secure or non secure vector base address, FCSE PID, Context PID*/
+	mrc	p15, 0, r4, c12, c0, 0
+	mrc	p15, 0, r5, c13, c0, 0
+	mrc	p15, 0, r6, c13, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Primary remap, normal remap registers */
+	mrc	p15, 0, r4, c10, c2, 0
+	mrc	p15, 0, r5, c10, c2, 1
+	stmia	r8!,{r4-r5}
+
+	/* Store current cpsr*/
+	mrs	r2, cpsr
+	stmia	r8!, {r2}
+
+	mrc	p15, 0, r4, c1, c0, 0
+	/* save control register */
+	stmia	r8!, {r4}
+clean_caches:
+	/* Clean Data or unified cache to POU*/
+	/* How to invalidate only L1 cache???? - #FIX_ME# */
+	/* mcr	p15, 0, r11, c7, c11, 1 */
+	cmp	r9, #1 /* Check whether L2 inval is required or not*/
+	bne	skip_l2_inval
+clean_l2:
+	/* read clidr */
+	mrc     p15, 1, r0, c0, c0, 1
+	/* extract loc from clidr */
+	ands    r3, r0, #0x7000000
+	/* left align loc bit field */
+	mov     r3, r3, lsr #23
+	/* if loc is 0, then no need to clean */
+	beq     finished
+	/* start clean at cache level 0 */
+	mov     r10, #0
+loop1:
+	/* work out 3x current cache level */
+	add     r2, r10, r10, lsr #1
+	/* extract cache type bits from clidr*/
+	mov     r1, r0, lsr r2
+	/* mask of the bits for current cache only */
+	and     r1, r1, #7
+	/* see what cache we have at this level */
+	cmp     r1, #2
+	/* skip if no cache, or just i-cache */
+	blt     skip
+	/* select current cache level in cssr */
+	mcr     p15, 2, r10, c0, c0, 0
+	/* isb to sych the new cssr&csidr */
+	isb
+	/* read the new csidr */
+	mrc     p15, 1, r1, c0, c0, 0
+	/* extract the length of the cache lines */
+	and     r2, r1, #7
+	/* add 4 (line length offset) */
+	add     r2, r2, #4
+	ldr     r4, assoc_mask
+	/* find maximum number on the way size */
+	ands    r4, r4, r1, lsr #3
+	/* find bit position of way size increment */
+	clz     r5, r4
+	ldr     r7, numset_mask
+	/* extract max number of the index size*/
+	ands    r7, r7, r1, lsr #13
+loop2:
+	mov     r9, r4
+	/* create working copy of max way size*/
+loop3:
+	/* factor way and cache number into r11 */
+	orr     r11, r10, r9, lsl r5
+	/* factor index number into r11 */
+	orr     r11, r11, r7, lsl r2
+	/*clean & invalidate by set/way */
+	mcr     p15, 0, r11, c7, c10, 2
+	/* decrement the way*/
+	subs    r9, r9, #1
+	bge     loop3
+	/*decrement the index */
+	subs    r7, r7, #1
+	bge     loop2
+skip:
+	add     r10, r10, #2
+	/* increment cache number */
+	cmp     r3, r10
+	bgt     loop1
+finished:
+	/*swith back to cache level 0 */
+	mov     r10, #0
+	/* select current cache level in cssr */
+	mcr     p15, 2, r10, c0, c0, 0
+	isb
+skip_l2_inval:
+	/* Data memory barrier and Data sync barrier */
+	mov     r1, #0
+	mcr     p15, 0, r1, c7, c10, 4
+	mcr     p15, 0, r1, c7, c10, 5
+
+	wfi                             @ wait for interrupt
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bl i_dll_wait
+	/* restore regs and return */
+	ldmfd   sp!, {r0-r12, pc}
+
+i_dll_wait:
+	ldr     r4, clk_stabilize_delay
+
+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
+pm_prepwstst_core:
+	.word	PM_PREPWSTST_CORE_V
+pm_prepwstst_mpu:
+	.word	PM_PREPWSTST_MPU_V
+pm_pwstctrl_mpu:
+	.word	PM_PWSTCTRL_MPU_P
+scratchpad_base:
+	.word	SCRATCHPAD_BASE_P
+sdrc_power:
+	.word SDRC_POWER_V
+context_mem:
+	.word	0x803E3E14
+clk_stabilize_delay:
+	.word 0x000001FF
+assoc_mask:
+	.word	0x3ff
+numset_mask:
+	.word	0x7fff
+ttbrbit_mask:
+	.word	0xFFFFC000
+table_index_mask:
+	.word	0xFFF00000
+table_entry:
+	.word	0x00000C02
+cache_pred_disable_mask:
+	.word	0xFFFFE7FB
+ENTRY(omap34xx_cpu_suspend_sz)
+	.word	. - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 34a56a1..215d463 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -28,7 +28,6 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/pm.h>
 #include <mach/mux.h>
 #include <mach/usb.h>
 
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 9dd68fa..4bc9ed7 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -171,7 +171,7 @@ endchoice
 
 config OMAP_SERIAL_WAKE
 	bool "Enable wake-up events for serial ports"
-	depends on OMAP_MUX
+	depends on ARCH_OMAP1 && OMAP_MUX
 	default y
 	help
 	  Select this option if you want to have your system wake up
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 70b68ef..86ee23d 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h
deleted file mode 100644
index ce6ee79..0000000
--- a/arch/arm/plat-omap/include/mach/pm.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/pm.h
- *
- * Header file for OMAP Power Management Routines
- *
- * Author: MontaVista Software, Inc.
- *	   support@mvista.com
- *
- * Copyright 2002 MontaVista Software Inc.
- *
- * Cleanup 2004 for Linux 2.6 by Dirk Behme <dirk.behme@de.bosch.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP_PM_H
-#define __ASM_ARCH_OMAP_PM_H
-
-/*
- * ----------------------------------------------------------------------------
- * Register and offset definitions to be used in PM assembler code
- * ----------------------------------------------------------------------------
- */
-#define CLKGEN_REG_ASM_BASE		IO_ADDRESS(0xfffece00)
-#define ARM_IDLECT1_ASM_OFFSET		0x04
-#define ARM_IDLECT2_ASM_OFFSET		0x08
-
-#define TCMIF_ASM_BASE			IO_ADDRESS(0xfffecc00)
-#define EMIFS_CONFIG_ASM_OFFSET		0x0c
-#define EMIFF_SDRAM_CONFIG_ASM_OFFSET	0x20
-
-/*
- * ----------------------------------------------------------------------------
- * Power management bitmasks
- * ----------------------------------------------------------------------------
- */
-#define IDLE_WAIT_CYCLES		0x00000fff
-#define PERIPHERAL_ENABLE		0x2
-
-#define SELF_REFRESH_MODE		0x0c000001
-#define IDLE_EMIFS_REQUEST		0xc
-#define MODEM_32K_EN			0x1
-#define PER_EN				0x1
-
-#define CPU_SUSPEND_SIZE		200
-#define ULPD_LOW_PWR_EN			0x0001
-#define ULPD_DEEP_SLEEP_TRANSITION_EN	0x0010
-#define ULPD_SETUP_ANALOG_CELL_3_VAL	0
-#define ULPD_POWER_CTRL_REG_VAL		0x0219
-
-#define DSP_IDLE_DELAY			10
-#define DSP_IDLE			0x0040
-#define DSP_RST				0x0004
-#define DSP_ENABLE			0x0002
-#define SUFFICIENT_DSP_RESET_TIME	1000
-#define DEFAULT_MPUI_CONFIG		0x05cf
-#define ENABLE_XORCLK			0x2
-#define DSP_CLOCK_ENABLE		0x2000
-#define DSP_IDLE_MODE			0x2
-#define TC_IDLE_REQUEST			(0x0000000c)
-
-#define IRQ_LEVEL2			(1<<0)
-#define IRQ_KEYBOARD			(1<<1)
-#define IRQ_UART2			(1<<15)
-
-#define PDE_BIT				0x08
-#define PWD_EN_BIT			0x04
-#define EN_PERCK_BIT			0x04
-
-#define OMAP1510_DEEP_SLEEP_REQUEST	0x0ec7
-#define OMAP1510_BIG_SLEEP_REQUEST	0x0cc5
-#define OMAP1510_IDLE_LOOP_REQUEST	0x0c00
-#define OMAP1510_IDLE_CLOCK_DOMAINS	0x2
-
-/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
-#define OMAP1610_IDLECT1_SLEEP_VAL	0x13c7
-#define OMAP1610_IDLECT2_SLEEP_VAL	0x09c7
-#define OMAP1610_IDLECT3_VAL		0x3f
-#define OMAP1610_IDLECT3_SLEEP_ORMASK	0x2c
-#define OMAP1610_IDLECT3		0xfffece24
-#define OMAP1610_IDLE_LOOP_REQUEST	0x0400
-
-#define OMAP730_IDLECT1_SLEEP_VAL	0x16c7
-#define OMAP730_IDLECT2_SLEEP_VAL	0x09c7
-#define OMAP730_IDLECT3_VAL		0x3f
-#define OMAP730_IDLECT3		0xfffece24
-#define OMAP730_IDLE_LOOP_REQUEST	0x0C00
-
-#if     !defined(CONFIG_ARCH_OMAP730) && \
-	!defined(CONFIG_ARCH_OMAP15XX) && \
-	!defined(CONFIG_ARCH_OMAP16XX) && \
-	!defined(CONFIG_ARCH_OMAP24XX)
-#warning "Power management for this processor not implemented yet"
-#endif
-
-#ifndef __ASSEMBLER__
-
-#include <linux/clk.h>
-
-extern void prevent_idle_sleep(void);
-extern void allow_idle_sleep(void);
-
-extern void omap_pm_idle(void);
-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, void __iomem *sdrc_dlla_ctrl,
-					void __iomem *sdrc_power);
-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);
-#else
-#define omap_serial_wakeup_init()	{}
-#define omap_serial_wake_trigger(x)	{}
-#endif	/* CONFIG_OMAP_SERIAL_WAKE */
-
-#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]
-
-#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
-#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
-#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
-
-#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
-#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
-#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
-
-#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x))
-#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]
-
-#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
-#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
-
-#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
-#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
- * with the stack pointer in sleep.S.
- */
-
-enum arm_save_state {
-	ARM_SLEEP_SAVE_START = 0,
-	/*
-	 * MPU control registers 32 bits
-	 */
-	ARM_SLEEP_SAVE_ARM_CKCTL,
-	ARM_SLEEP_SAVE_ARM_IDLECT1,
-	ARM_SLEEP_SAVE_ARM_IDLECT2,
-	ARM_SLEEP_SAVE_ARM_IDLECT3,
-	ARM_SLEEP_SAVE_ARM_EWUPCT,
-	ARM_SLEEP_SAVE_ARM_RSTCT1,
-	ARM_SLEEP_SAVE_ARM_RSTCT2,
-	ARM_SLEEP_SAVE_ARM_SYSST,
-	ARM_SLEEP_SAVE_SIZE
-};
-
-enum dsp_save_state {
-	DSP_SLEEP_SAVE_START = 0,
-	/*
-	 * DSP registers 16 bits
-	 */
-	DSP_SLEEP_SAVE_DSP_IDLECT2,
-	DSP_SLEEP_SAVE_SIZE
-};
-
-enum ulpd_save_state {
-	ULPD_SLEEP_SAVE_START = 0,
-	/*
-	 * ULPD registers 16 bits
-	 */
-	ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
-	ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
-	ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
-	ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
-	ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
-	ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
-	ULPD_SLEEP_SAVE_SIZE
-};
-
-enum mpui1510_save_state {
-	MPUI1510_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI1510_SLEEP_SAVE_MPUI_CTRL,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
-#if defined(CONFIG_ARCH_OMAP15XX)
-	MPUI1510_SLEEP_SAVE_SIZE
-#else
-	MPUI1510_SLEEP_SAVE_SIZE = 0
-#endif
-};
-
-enum mpui730_save_state {
-	MPUI730_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI730_SLEEP_SAVE_MPUI_CTRL,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI730_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI730_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR,
-	MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR,
-#if defined(CONFIG_ARCH_OMAP730)
-	MPUI730_SLEEP_SAVE_SIZE
-#else
-	MPUI730_SLEEP_SAVE_SIZE = 0
-#endif
-};
-
-enum mpui1610_save_state {
-	MPUI1610_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI1610_SLEEP_SAVE_MPUI_CTRL,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
-#if defined(CONFIG_ARCH_OMAP16XX)
-	MPUI1610_SLEEP_SAVE_SIZE
-#else
-	MPUI1610_SLEEP_SAVE_SIZE = 0
-#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_CLKSTCTRL_MPU,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM,
-
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM,
-
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM,
-
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM,
-
-	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_ICLKEN3_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 */
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index f2e9de1..6391e3d 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -39,7 +39,6 @@
 #include <mach/gpmc.h>
 #include <mach/onenand.h>
 #include <mach/gpio.h>
-#include <mach/pm.h>
 
 #include <mach/dma.h>
 
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/13] OMAP: Add new function to check wether there is irq pending
  2009-05-20 23:19   ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Kevin Hilman
@ 2009-05-20 23:19     ` Kevin Hilman
  2009-05-20 23:19       ` [PATCH 04/13] OMAP3: PM: Force IVA2 into idle during bootup Kevin Hilman
  2009-05-28 15:48     ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Russell King - ARM Linux
  1 sibling, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

From: Jouni Hogander <jouni.hogander@nokia.com>

Add common omap2/3 function to check wether there is irq pending.
Switch to use it in omap2 pm code instead of its own.

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/irq.c              |   17 ++++++++++++++++-
 arch/arm/mach-omap2/pm24xx.c           |   19 +++----------------
 arch/arm/plat-omap/include/mach/irqs.h |    1 +
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 08a3b99..b828638 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -28,7 +28,6 @@
 #define INTC_MIR_CLEAR0		0x0088
 #define INTC_MIR_SET0		0x008c
 #define INTC_PENDING_IRQ0	0x0098
-
 /* Number of IRQ state bits in each MIR register */
 #define IRQ_BITS_PER_REG	32
 
@@ -156,6 +155,22 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
 	intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
 }
 
+int omap_irq_pending(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
+		struct omap_irq_bank *bank = irq_banks + i;
+		int irq;
+
+		for (irq = 0; irq < bank->nr_irqs; irq += 32)
+			if (intc_bank_read_reg(bank, INTC_PENDING_IRQ0 +
+					       ((irq >> 5) << 5)))
+				return 1;
+	}
+	return 0;
+}
+
 void __init omap_init_irq(void)
 {
 	unsigned long nr_of_irqs = 0;
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 384a5b5..3fa9c7c 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -77,19 +77,6 @@ static int omap2_fclks_active(void)
 	return 0;
 }
 
-static int omap2_irq_pending(void)
-{
-	u32 pending_reg = 0x480fe098;
-	int i;
-
-	for (i = 0; i < 4; i++) {
-		if (omap_readl(pending_reg))
-			return 1;
-		pending_reg += 0x20;
-	}
-	return 0;
-}
-
 static void omap2_enter_full_retention(void)
 {
 	u32 l;
@@ -128,7 +115,7 @@ static void omap2_enter_full_retention(void)
 
 	/* One last check for pending IRQs to avoid extra latency due
 	 * to sleeping unnecessarily. */
-	if (omap2_irq_pending())
+	if (omap_irq_pending())
 		goto no_sleep;
 
 	/* Jump to SRAM suspend code */
@@ -265,13 +252,13 @@ static void omap2_pm_idle(void)
 	local_fiq_disable();
 
 	if (!omap2_can_sleep()) {
-		if (omap2_irq_pending())
+		if (omap_irq_pending())
 			goto out;
 		omap2_enter_mpu_retention();
 		goto out;
 	}
 
-	if (omap2_irq_pending())
+	if (omap_irq_pending())
 		goto out;
 
 	omap2_enter_full_retention();
diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h
index 7f57ee6..f5f7c92 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -467,6 +467,7 @@
 
 #ifndef __ASSEMBLY__
 extern void omap_init_irq(void);
+extern int omap_irq_pending(void);
 #endif
 
 #include <mach/hardware.h>
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/13] OMAP3: PM: Force IVA2 into idle during bootup
  2009-05-20 23:19     ` [PATCH 03/13] OMAP: Add new function to check wether there is irq pending Kevin Hilman
@ 2009-05-20 23:19       ` Kevin Hilman
  2009-05-20 23:19         ` [PATCH 05/13] OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/pm34xx.c              |   50 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/mach/control.h |    5 +++
 2 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 61ccaf3..2340869 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -357,6 +357,54 @@ static struct platform_suspend_ops omap_pm_ops = {
 	.valid		= suspend_valid_only_mem,
 };
 
+
+/**
+ * omap3_iva_idle(): ensure IVA is in idle so it can be put into
+ *                   retention
+ *
+ * In cases where IVA2 is activated by bootcode, it may prevent
+ * full-chip retention or off-mode because it is not idle.  This
+ * function forces the IVA2 into idle state so it can go
+ * into retention/off and thus allow full-chip retention/off.
+ *
+ **/
+static void __init omap3_iva_idle(void)
+{
+	/* ensure IVA2 clock is disabled */
+	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* if no clock activity, nothing else to do */
+	if (!(cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
+	      OMAP3430_CLKACTIVITY_IVA2_MASK))
+		return;
+
+	/* Reset IVA2 */
+	prm_write_mod_reg(OMAP3430_RST1_IVA2 |
+			  OMAP3430_RST2_IVA2 |
+			  OMAP3430_RST3_IVA2,
+			  OMAP3430_IVA2_MOD, RM_RSTCTRL);
+
+	/* Enable IVA2 clock */
+	cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
+			 OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Set IVA2 boot mode to 'idle' */
+	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
+			 OMAP343X_CONTROL_IVA2_BOOTMOD);
+
+	/* Un-reset IVA2 */
+	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
+
+	/* Disable IVA2 clock */
+	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Reset IVA2 */
+	prm_write_mod_reg(OMAP3430_RST1_IVA2 |
+			  OMAP3430_RST2_IVA2 |
+			  OMAP3430_RST3_IVA2,
+			  OMAP3430_IVA2_MOD, RM_RSTCTRL);
+}
+
 static void __init prcm_setup_regs(void)
 {
 	/* reset modem */
@@ -516,6 +564,8 @@ static void __init prcm_setup_regs(void)
 	 * it is selected to mpu wakeup goup */
 	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+
+	omap3_iva_idle();
 }
 
 static int __init pwrdms_setup(struct powerdomain *pwrdm)
diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h
index 269147f..d38697b 100644
--- a/arch/arm/plat-omap/include/mach/control.h
+++ b/arch/arm/plat-omap/include/mach/control.h
@@ -189,6 +189,11 @@
 #define OMAP2_PBIASLITEPWRDNZ0		(1 << 1)
 #define OMAP2_PBIASLITEVMODE0		(1 << 0)
 
+/* CONTROL_IVA2_BOOTMOD bits */
+#define OMAP3_IVA2_BOOTMOD_SHIFT	0
+#define OMAP3_IVA2_BOOTMOD_MASK		(0xf << 0)
+#define OMAP3_IVA2_BOOTMOD_IDLE		(0x1 << 0)
+
 #ifndef __ASSEMBLY__
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 extern void __iomem *omap_ctrl_base_get(void);
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/13] OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X
  2009-05-20 23:19       ` [PATCH 04/13] OMAP3: PM: Force IVA2 into idle during bootup Kevin Hilman
@ 2009-05-20 23:19         ` Kevin Hilman
  2009-05-20 23:19           ` [PATCH 06/13] OMAP3: PM: UART: disable clocks when idle and off-mode support Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/plat-omap/include/mach/control.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h
index d38697b..a9f05e5 100644
--- a/arch/arm/plat-omap/include/mach/control.h
+++ b/arch/arm/plat-omap/include/mach/control.h
@@ -194,6 +194,10 @@
 #define OMAP3_IVA2_BOOTMOD_MASK		(0xf << 0)
 #define OMAP3_IVA2_BOOTMOD_IDLE		(0x1 << 0)
 
+/* CONTROL_PADCONF_X bits */
+#define OMAP3_PADCONF_WAKEUPEVENT0	(1 << 15)
+#define OMAP3_PADCONF_WAKEUPENABLE0	(1 << 14)
+
 #ifndef __ASSEMBLY__
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 extern void __iomem *omap_ctrl_base_get(void);
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/13] OMAP3: PM: UART: disable clocks when idle and off-mode support
  2009-05-20 23:19         ` [PATCH 05/13] OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X Kevin Hilman
@ 2009-05-20 23:19           ` Kevin Hilman
  2009-05-20 23:19             ` [PATCH 07/13] OMAP: UART: Add sysfs interface for adjusting UART sleep timeout Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

This patch allows the UART clocks to be disabled when the OMAP UARTs
are inactive, thus permitting the chip to hit retention in idle.
After the timeout of an activity timer, each UART is allowed to
disable its clocks so the system can enter retention.  The activity
timer is (re)activated on any UART interrupt, UART wake event or any
IO pad wakeup.  The actual disable of the UART clocks is done in the
'prepare_idle' hook called from the OMAP idle loop.

While the activity timer is active, the smart-idle mode of the UART is
also disabled.  This is due to a "feature" of the UART module that
after a UART wakeup, the smart-idle mode may be entered before the
UART has communicated the interrupt, or upon TX, an idle mode may be
entered before the TX FIFOs are emptied.

Upon suspend, the 'prepare_suspend' hook cancels any pending activity
timers and allows the clocks to be disabled.

In addition, upon disabling clocks the UART state is saved in case
of an off-mode transition while clocks are off.

Special thanks to Tero Kristo for the initial ideas and first versions
of UART idle support, and to Jouni Hogander for extra testing and
bugfixes.

Tested on OMAP3 (Beagle, custom HW) and OMAP2 (n810)

Cc: Tero Kristo <tero.kristo@nokia.com>
Cc: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/pm24xx.c             |   16 ++-
 arch/arm/mach-omap2/pm34xx.c             |   15 ++
 arch/arm/mach-omap2/serial.c             |  388 ++++++++++++++++++++++++++++--
 arch/arm/plat-omap/include/mach/common.h |    2 -
 arch/arm/plat-omap/include/mach/serial.h |    9 +
 5 files changed, 403 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 3fa9c7c..4ef8a0d 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -72,6 +72,11 @@ static int omap2_fclks_active(void)
 
 	f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 	f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+
+	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
+	f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
+	f2 &= ~OMAP24XX_EN_UART3;
+
 	if (f1 | f2)
 		return 1;
 	return 0;
@@ -118,12 +123,20 @@ static void omap2_enter_full_retention(void)
 	if (omap_irq_pending())
 		goto no_sleep;
 
+	omap_uart_prepare_idle(0);
+	omap_uart_prepare_idle(1);
+	omap_uart_prepare_idle(2);
+
 	/* Jump to SRAM suspend code */
 	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
 			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
 			   OMAP_SDRC_REGADDR(SDRC_POWER));
-no_sleep:
 
+	omap_uart_resume_idle(2);
+	omap_uart_resume_idle(1);
+	omap_uart_resume_idle(0);
+
+no_sleep:
 	if (omap2_pm_debug) {
 		unsigned long long tmp;
 
@@ -288,6 +301,7 @@ static int omap2_pm_suspend(void)
 	mir1 = omap_readl(0x480fe0a4);
 	omap_writel(1 << 5, 0x480fe0ac);
 
+	omap_uart_prepare_suspend();
 	omap2_enter_full_retention();
 
 	omap_writel(mir1, 0x480fe0a4);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2340869..6c91e43 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -27,6 +27,7 @@
 #include <mach/clockdomain.h>
 #include <mach/powerdomain.h>
 #include <mach/control.h>
+#include <mach/serial.h>
 
 #include "cm.h"
 #include "cm-regbits-34xx.h"
@@ -170,10 +171,16 @@ static void omap_sram_idle(void)
 		return;
 	}
 	omap2_gpio_prepare_for_retention();
+	omap_uart_prepare_idle(0);
+	omap_uart_prepare_idle(1);
+	omap_uart_prepare_idle(2);
 
 	_omap_sram_idle(NULL, save_state);
 	cpu_init();
 
+	omap_uart_resume_idle(2);
+	omap_uart_resume_idle(1);
+	omap_uart_resume_idle(0);
 	omap2_gpio_resume_after_retention();
 }
 
@@ -206,6 +213,11 @@ static int omap3_fclks_active(void)
 				  CM_FCLKEN);
 	fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
 				  CM_FCLKEN);
+
+	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
+	fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2);
+	fck_per &= ~OMAP3430_EN_UART3;
+
 	if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
 	    fck_cam | fck_per | fck_usbhost)
 		return 1;
@@ -216,6 +228,8 @@ static int omap3_can_sleep(void)
 {
 	if (!enable_dyn_sleep)
 		return 0;
+	if (!omap_uart_can_sleep())
+		return 0;
 	if (omap3_fclks_active())
 		return 0;
 	return 1;
@@ -306,6 +320,7 @@ static int omap3_pm_suspend(void)
 			goto restore;
 	}
 
+	omap_uart_prepare_suspend();
 	omap_sram_idle();
 
 restore:
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 4dcf39c..50bff3d 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -6,6 +6,8 @@
  * Copyright (C) 2005-2008 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
+ * Major rework for PM support by Kevin Hilman
+ *
  * Based off of arch/arm/mach-omap/omap1/serial.c
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -21,9 +23,48 @@
 
 #include <mach/common.h>
 #include <mach/board.h>
+#include <mach/clock.h>
+#include <mach/control.h>
+
+#include "prm.h"
+#include "pm.h"
+#include "prm-regbits-34xx.h"
+
+#define DEFAULT_TIMEOUT (2 * HZ)
+
+struct omap_uart_state {
+	int num;
+	int can_sleep;
+	struct timer_list timer;
+	u32 timeout;
 
-static struct clk *uart_ick[OMAP_MAX_NR_PORTS];
-static struct clk *uart_fck[OMAP_MAX_NR_PORTS];
+	void __iomem *wk_st;
+	void __iomem *wk_en;
+	u32 wk_mask;
+	u32 padconf;
+
+	struct clk *ick;
+	struct clk *fck;
+	int clocked;
+
+	struct plat_serial8250_port *p;
+	struct list_head node;
+
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+	int context_valid;
+
+	/* Registers to be saved/restored for OFF-mode */
+	u16 dll;
+	u16 dlh;
+	u16 ier;
+	u16 sysc;
+	u16 scr;
+	u16 wer;
+#endif
+};
+
+static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
+static LIST_HEAD(uart_list);
 
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
@@ -74,30 +115,320 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
  * properly. Note that the TX watermark initialization may not be needed
  * once the 8250.c watermark handling code is merged.
  */
-static inline void __init omap_serial_reset(struct plat_serial8250_port *p)
+static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
+	struct plat_serial8250_port *p = uart->p;
+
 	serial_write_reg(p, UART_OMAP_MDR1, 0x07);
 	serial_write_reg(p, UART_OMAP_SCR, 0x08);
 	serial_write_reg(p, UART_OMAP_MDR1, 0x00);
 	serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
 }
 
-void omap_serial_enable_clocks(int enable)
+#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)
 {
-	int i;
-	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
-		if (uart_ick[i] && uart_fck[i]) {
-			if (enable) {
-				clk_enable(uart_ick[i]);
-				clk_enable(uart_fck[i]);
-			} else {
-				clk_disable(uart_ick[i]);
-				clk_disable(uart_fck[i]);
+	u16 lcr = 0;
+	struct plat_serial8250_port *p = uart->p;
+
+	if (!enable_off_mode)
+		return;
+
+	lcr = serial_read_reg(p, UART_LCR);
+	serial_write_reg(p, UART_LCR, 0xBF);
+	uart->dll = serial_read_reg(p, UART_DLL);
+	uart->dlh = serial_read_reg(p, UART_DLM);
+	serial_write_reg(p, UART_LCR, lcr);
+	uart->ier = serial_read_reg(p, UART_IER);
+	uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
+	uart->scr = serial_read_reg(p, UART_OMAP_SCR);
+	uart->wer = serial_read_reg(p, UART_OMAP_WER);
+
+	uart->context_valid = 1;
+}
+
+static void omap_uart_restore_context(struct omap_uart_state *uart)
+{
+	u16 efr = 0;
+	struct plat_serial8250_port *p = uart->p;
+
+	if (!enable_off_mode)
+		return;
+
+	if (!uart->context_valid)
+		return;
+
+	uart->context_valid = 0;
+
+	serial_write_reg(p, UART_OMAP_MDR1, 0x7);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	efr = serial_read_reg(p, UART_EFR);
+	serial_write_reg(p, UART_EFR, UART_EFR_ECB);
+	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(p, UART_IER, 0x0);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(p, UART_DLL, uart->dll);
+	serial_write_reg(p, UART_DLM, uart->dlh);
+	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(p, UART_IER, uart->ier);
+	serial_write_reg(p, UART_FCR, 0xA1);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(p, UART_EFR, efr);
+	serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
+	serial_write_reg(p, UART_OMAP_SCR, uart->scr);
+	serial_write_reg(p, UART_OMAP_WER, uart->wer);
+	serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
+	serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+}
+#else
+static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
+static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
+#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
+
+static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
+{
+	if (uart->clocked)
+		return;
+
+	clk_enable(uart->ick);
+	clk_enable(uart->fck);
+	uart->clocked = 1;
+	omap_uart_restore_context(uart);
+}
+
+#ifdef CONFIG_PM
+
+static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
+{
+	if (!uart->clocked)
+		return;
+
+	omap_uart_save_context(uart);
+	uart->clocked = 0;
+	clk_disable(uart->ick);
+	clk_disable(uart->fck);
+}
+
+static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
+					  int enable)
+{
+	struct plat_serial8250_port *p = uart->p;
+	u16 sysc;
+
+	sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
+	if (enable)
+		sysc |= 0x2 << 3;
+	else
+		sysc |= 0x1 << 3;
+
+	serial_write_reg(p, UART_OMAP_SYSC, sysc);
+}
+
+static void omap_uart_block_sleep(struct omap_uart_state *uart)
+{
+	omap_uart_enable_clocks(uart);
+
+	omap_uart_smart_idle_enable(uart, 0);
+	uart->can_sleep = 0;
+	mod_timer(&uart->timer, jiffies + uart->timeout);
+}
+
+static void omap_uart_allow_sleep(struct omap_uart_state *uart)
+{
+	if (!uart->clocked)
+		return;
+
+	omap_uart_smart_idle_enable(uart, 1);
+	uart->can_sleep = 1;
+	del_timer(&uart->timer);
+}
+
+static void omap_uart_idle_timer(unsigned long data)
+{
+	struct omap_uart_state *uart = (struct omap_uart_state *)data;
+
+	omap_uart_allow_sleep(uart);
+}
+
+void omap_uart_prepare_idle(int num)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (num == uart->num && uart->can_sleep) {
+			omap_uart_disable_clocks(uart);
+			return;
+		}
+	}
+}
+
+void omap_uart_resume_idle(int num)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (num == uart->num) {
+			omap_uart_enable_clocks(uart);
+
+			/* Check for IO pad wakeup */
+			if (cpu_is_omap34xx() && uart->padconf) {
+				u16 p = omap_ctrl_readw(uart->padconf);
+
+				if (p & OMAP3_PADCONF_WAKEUPEVENT0)
+					omap_uart_block_sleep(uart);
 			}
+
+			/* Check for normal UART wakeup */
+			if (__raw_readl(uart->wk_st) & uart->wk_mask)
+				omap_uart_block_sleep(uart);
+
+			return;
+		}
+	}
+}
+
+void omap_uart_prepare_suspend(void)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		omap_uart_allow_sleep(uart);
+	}
+}
+
+int omap_uart_can_sleep(void)
+{
+	struct omap_uart_state *uart;
+	int can_sleep = 1;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (!uart->clocked)
+			continue;
+
+		if (!uart->can_sleep) {
+			can_sleep = 0;
+			continue;
+		}
+
+		/* This UART can now safely sleep. */
+		omap_uart_allow_sleep(uart);
+	}
+
+	return can_sleep;
+}
+
+/**
+ * omap_uart_interrupt()
+ *
+ * This handler is used only to detect that *any* UART interrupt has
+ * occurred.  It does _nothing_ to handle the interrupt.  Rather,
+ * any UART interrupt will trigger the inactivity timer so the
+ * UART will not idle or sleep for its timeout period.
+ *
+ **/
+static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
+{
+	struct omap_uart_state *uart = dev_id;
+
+	omap_uart_block_sleep(uart);
+
+	return IRQ_NONE;
+}
+
+static void omap_uart_idle_init(struct omap_uart_state *uart)
+{
+	u32 v;
+	struct plat_serial8250_port *p = uart->p;
+	int ret;
+
+	uart->can_sleep = 0;
+	uart->timeout = DEFAULT_TIMEOUT;
+	setup_timer(&uart->timer, omap_uart_idle_timer,
+		    (unsigned long) uart);
+	mod_timer(&uart->timer, jiffies + uart->timeout);
+	omap_uart_smart_idle_enable(uart, 0);
+
+	if (cpu_is_omap34xx()) {
+		u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+		u32 wk_mask = 0;
+		u32 padconf = 0;
+
+		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
+		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
+		switch (uart->num) {
+		case 0:
+			wk_mask = OMAP3430_ST_UART1_MASK;
+			padconf = 0x182;
+			break;
+		case 1:
+			wk_mask = OMAP3430_ST_UART2_MASK;
+			padconf = 0x17a;
+			break;
+		case 2:
+			wk_mask = OMAP3430_ST_UART3_MASK;
+			padconf = 0x19e;
+			break;
 		}
+		uart->wk_mask = wk_mask;
+		uart->padconf = padconf;
+	} else if (cpu_is_omap24xx()) {
+		u32 wk_mask = 0;
+
+		if (cpu_is_omap2430()) {
+			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
+		} else if (cpu_is_omap2420()) {
+			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
+		}
+		switch (uart->num) {
+		case 0:
+			wk_mask = OMAP24XX_ST_UART1_MASK;
+			break;
+		case 1:
+			wk_mask = OMAP24XX_ST_UART2_MASK;
+			break;
+		case 2:
+			wk_mask = OMAP24XX_ST_UART3_MASK;
+			break;
+		}
+		uart->wk_mask = wk_mask;
+	} else {
+		uart->wk_en = 0;
+		uart->wk_st = 0;
+		uart->wk_mask = 0;
+		uart->padconf = 0;
+	}
+
+	/* Set wake-enable bit */
+	if (uart->wk_en && uart->wk_mask) {
+		v = __raw_readl(uart->wk_en);
+		v |= uart->wk_mask;
+		__raw_writel(v, uart->wk_en);
+	}
+
+	/* Ensure IOPAD wake-enables are set */
+	if (cpu_is_omap34xx() && uart->padconf) {
+		u16 v;
+
+		v = omap_ctrl_readw(uart->padconf);
+		v |= OMAP3_PADCONF_WAKEUPENABLE0;
+		omap_ctrl_writew(v, uart->padconf);
 	}
+
+	p->flags |= UPF_SHARE_IRQ;
+	ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
+			  "serial idle", (void *)uart);
+	WARN_ON(ret);
 }
 
+#else
+static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+#endif /* CONFIG_PM */
+
 void __init omap_serial_init(void)
 {
 	int i;
@@ -117,6 +448,7 @@ void __init omap_serial_init(void)
 
 	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
 		struct plat_serial8250_port *p = serial_platform_data + i;
+		struct omap_uart_state *uart = &omap_uart[i];
 
 		if (!(info->enabled_uarts & (1 << i))) {
 			p->membase = NULL;
@@ -125,22 +457,30 @@ void __init omap_serial_init(void)
 		}
 
 		sprintf(name, "uart%d_ick", i+1);
-		uart_ick[i] = clk_get(NULL, name);
-		if (IS_ERR(uart_ick[i])) {
+		uart->ick = clk_get(NULL, name);
+		if (IS_ERR(uart->ick)) {
 			printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
-			uart_ick[i] = NULL;
-		} else
-			clk_enable(uart_ick[i]);
+			uart->ick = NULL;
+		}
 
 		sprintf(name, "uart%d_fck", i+1);
-		uart_fck[i] = clk_get(NULL, name);
-		if (IS_ERR(uart_fck[i])) {
+		uart->fck = clk_get(NULL, name);
+		if (IS_ERR(uart->fck)) {
 			printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
-			uart_fck[i] = NULL;
-		} else
-			clk_enable(uart_fck[i]);
+			uart->fck = NULL;
+		}
+
+		if (!uart->ick || !uart->fck)
+			continue;
+
+		uart->num = i;
+		p->private_data = uart;
+		uart->p = p;
+		list_add(&uart->node, &uart_list);
 
-		omap_serial_reset(p);
+		omap_uart_enable_clocks(uart);
+		omap_uart_reset(uart);
+		omap_uart_idle_init(uart);
 	}
 }
 
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h
index 0ecf36d..834f0b3 100644
--- a/arch/arm/plat-omap/include/mach/common.h
+++ b/arch/arm/plat-omap/include/mach/common.h
@@ -33,8 +33,6 @@ struct sys_timer;
 
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
-extern void omap_serial_init(void);
-extern void omap_serial_enable_clocks(int enable);
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
 				 struct i2c_board_info const *info,
diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h
index 8a676a0..8e89585 100644
--- a/arch/arm/plat-omap/include/mach/serial.h
+++ b/arch/arm/plat-omap/include/mach/serial.h
@@ -40,4 +40,13 @@
 			__ret;						\
 			})
 
+#ifndef __ASSEMBLER__
+extern void omap_serial_init(void);
+extern int omap_uart_can_sleep(void);
+extern void omap_uart_check_wakeup(void);
+extern void omap_uart_prepare_suspend(void);
+extern void omap_uart_prepare_idle(int num);
+extern void omap_uart_resume_idle(int num);
+#endif
+
 #endif
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/13] OMAP: UART: Add sysfs interface for adjusting UART sleep timeout
  2009-05-20 23:19           ` [PATCH 06/13] OMAP3: PM: UART: disable clocks when idle and off-mode support Kevin Hilman
@ 2009-05-20 23:19             ` Kevin Hilman
  2009-05-20 23:19               ` [PATCH 08/13] OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

From: Jouni Hogander <jouni.hogander@nokia.com>

This patch makes it possible to change uart sleep timeout. New sysfs
entry is added (/sys/devices/platform/serial8250.<uart>/sleep_timeout)
Writing zero will disable the timeout feature and prevent UART clocks
from being disabled.

Also default timeout is increased to 5 second to make serial console
more usable.

Original patch was written by Tero Kristo.

Cc: Tero Kristo <Tero.Kristo@nokia.com>
Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/serial.c |   55 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 50bff3d..854ac94 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -30,7 +30,7 @@
 #include "pm.h"
 #include "prm-regbits-34xx.h"
 
-#define DEFAULT_TIMEOUT (2 * HZ)
+#define DEFAULT_TIMEOUT (5 * HZ)
 
 struct omap_uart_state {
 	int num;
@@ -233,7 +233,10 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 	omap_uart_smart_idle_enable(uart, 0);
 	uart->can_sleep = 0;
-	mod_timer(&uart->timer, jiffies + uart->timeout);
+	if (uart->timeout)
+		mod_timer(&uart->timer, jiffies + uart->timeout);
+	else
+		del_timer(&uart->timer);
 }
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
@@ -338,6 +341,8 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
+static u32 sleep_timeout = DEFAULT_TIMEOUT;
+
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
 	u32 v;
@@ -345,7 +350,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 	int ret;
 
 	uart->can_sleep = 0;
-	uart->timeout = DEFAULT_TIMEOUT;
+	uart->timeout = sleep_timeout;
 	setup_timer(&uart->timer, omap_uart_idle_timer,
 		    (unsigned long) uart);
 	mod_timer(&uart->timer, jiffies + uart->timeout);
@@ -425,6 +430,39 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 	WARN_ON(ret);
 }
 
+static ssize_t sleep_timeout_show(struct kobject *kobj,
+				  struct kobj_attribute *attr,
+				  char *buf)
+{
+	return sprintf(buf, "%u\n", sleep_timeout / HZ);
+}
+
+static ssize_t sleep_timeout_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t n)
+{
+	struct omap_uart_state *uart;
+	unsigned int value;
+
+	if (sscanf(buf, "%u", &value) != 1) {
+		printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
+		return -EINVAL;
+	}
+	sleep_timeout = value * HZ;
+	list_for_each_entry(uart, &uart_list, node) {
+		uart->timeout = sleep_timeout;
+		if (uart->timeout)
+			mod_timer(&uart->timer, jiffies + uart->timeout);
+		else
+			/* A zero value means disable timeout feature */
+			omap_uart_block_sleep(uart);
+	}
+	return n;
+}
+
+static struct kobj_attribute sleep_timeout_attr =
+	__ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
+
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
 #endif /* CONFIG_PM */
@@ -494,6 +532,15 @@ static struct platform_device serial_device = {
 
 static int __init omap_init(void)
 {
-	return platform_device_register(&serial_device);
+	int ret;
+
+	ret = platform_device_register(&serial_device);
+
+#ifdef CONFIG_PM
+	if (!ret)
+		ret = sysfs_create_file(&serial_device.dev.kobj,
+					&sleep_timeout_attr.attr);
+#endif
+	return ret;
 }
 arch_initcall(omap_init);
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/13] OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init
  2009-05-20 23:19             ` [PATCH 07/13] OMAP: UART: Add sysfs interface for adjusting UART sleep timeout Kevin Hilman
@ 2009-05-20 23:19               ` Kevin Hilman
  2009-05-20 23:19                 ` [PATCH 09/13] OMAP3: PM: D2D clockdomain supports SW supervised transitions Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Add D2D clocks (modem_fck, sad2d_ick, mad2d_ick) to clock framework
and ensure that auto-idle bits are set for these clocks during PRCM
init.

Also add omap3_d2d_idle() function called durint PRCM setup which
ensures D2D pins are MUX'd correctly to enable retention for
standalone (no-modem) devices.

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/clock34xx.c           |    3 ++
 arch/arm/mach-omap2/clock34xx.h           |   33 +++++++++++++++++++++++++++-
 arch/arm/mach-omap2/cm-regbits-34xx.h     |   14 ++++++++++++
 arch/arm/mach-omap2/pm34xx.c              |   25 ++++++++++++++++++++-
 arch/arm/plat-omap/include/mach/control.h |    4 +++
 5 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index ba05aa4..13a36cf 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -129,6 +129,9 @@ static struct omap_clk omap34xx_clks[] = {
 	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2),
 	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2),
 	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
+	CLK(NULL,	"modem_fck",	&modem_fck,	CK_343X),
+	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_343X),
+	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_343X),
 	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_343X),
 	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_343X),
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2),
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 496f0e9..e433aec 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -1230,6 +1230,37 @@ static struct clk d2d_26m_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk modem_fck = {
+	.name		= "modem_fck",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &sys_ck,
+	.init		= &omap2_init_clk_clkdm,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk sad2d_ick = {
+	.name		= "sad2d_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &l3_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk mad2d_ick = {
+	.name		= "mad2d_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &l3_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 static const struct clksel omap343x_gpt_clksel[] = {
 	{ .parent = &omap_32k_fck, .rates = gpt_32k_rates },
 	{ .parent = &sys_ck,	   .rates = gpt_sys_rates },
@@ -1947,8 +1978,6 @@ static struct clk usb_l4_ick = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */
-
 /* SECURITY_L4_ICK2 based clocks */
 
 static struct clk security_l4_ick2 = {
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 6f3f5a3..6923deb 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -145,6 +145,8 @@
 #define OMAP3430_CLKACTIVITY_MPU_MASK			(1 << 0)
 
 /* CM_FCLKEN1_CORE specific bits */
+#define OMAP3430_EN_MODEM				(1 << 31)
+#define OMAP3430_EN_MODEM_SHIFT				31
 
 /* CM_ICLKEN1_CORE specific bits */
 #define OMAP3430_EN_ICR					(1 << 29)
@@ -161,6 +163,8 @@
 #define OMAP3430_EN_MAILBOXES_SHIFT			7
 #define OMAP3430_EN_OMAPCTRL				(1 << 6)
 #define OMAP3430_EN_OMAPCTRL_SHIFT			6
+#define OMAP3430_EN_SAD2D				(1 << 3)
+#define OMAP3430_EN_SAD2D_SHIFT				3
 #define OMAP3430_EN_SDRC				(1 << 1)
 #define OMAP3430_EN_SDRC_SHIFT				1
 
@@ -176,6 +180,10 @@
 #define OMAP3430_EN_DES1				(1 << 0)
 #define OMAP3430_EN_DES1_SHIFT				0
 
+/* CM_ICLKEN3_CORE */
+#define OMAP3430_EN_MAD2D_SHIFT				3
+#define OMAP3430_EN_MAD2D				(1 << 3)
+
 /* CM_FCLKEN3_CORE specific bits */
 #define OMAP3430ES2_EN_TS_SHIFT				1
 #define OMAP3430ES2_EN_TS_MASK				(1 << 1)
@@ -231,6 +239,8 @@
 #define OMAP3430ES2_ST_CPEFUSE_MASK			(1 << 0)
 
 /* CM_AUTOIDLE1_CORE */
+#define OMAP3430_AUTO_MODEM				(1 << 31)
+#define OMAP3430_AUTO_MODEM_SHIFT			31
 #define OMAP3430ES2_AUTO_MMC3				(1 << 30)
 #define OMAP3430ES2_AUTO_MMC3_SHIFT			30
 #define OMAP3430ES2_AUTO_ICR				(1 << 29)
@@ -287,6 +297,8 @@
 #define OMAP3430_AUTO_HSOTGUSB_SHIFT			4
 #define OMAP3430ES1_AUTO_D2D				(1 << 3)
 #define OMAP3430ES1_AUTO_D2D_SHIFT			3
+#define OMAP3430_AUTO_SAD2D				(1 << 3)
+#define OMAP3430_AUTO_SAD2D_SHIFT			3
 #define OMAP3430_AUTO_SSI				(1 << 0)
 #define OMAP3430_AUTO_SSI_SHIFT				0
 
@@ -308,6 +320,8 @@
 #define	OMAP3430ES2_AUTO_USBTLL				(1 << 2)
 #define OMAP3430ES2_AUTO_USBTLL_SHIFT			2
 #define OMAP3430ES2_AUTO_USBTLL_MASK			(1 << 2)
+#define OMAP3430_AUTO_MAD2D_SHIFT			3
+#define OMAP3430_AUTO_MAD2D				(1 << 3)
 
 /* CM_CLKSEL_CORE */
 #define OMAP3430_CLKSEL_SSI_SHIFT			8
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 6c91e43..d41e2c5 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -420,14 +420,32 @@ static void __init omap3_iva_idle(void)
 			  OMAP3430_IVA2_MOD, RM_RSTCTRL);
 }
 
-static void __init prcm_setup_regs(void)
+static void __init omap3_d2d_idle(void)
 {
+	u16 mask, padconf;
+
+	/* In a stand alone OMAP3430 where there is not a stacked
+	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
+	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
+	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
+	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
+
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+
 	/* reset modem */
 	prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
 			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
 			  CORE_MOD, RM_RSTCTRL);
 	prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
+}
 
+static void __init prcm_setup_regs(void)
+{
 	/* XXX Reset all wkdeps. This should be done when initializing
 	 * powerdomains */
 	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -447,6 +465,7 @@ static void __init prcm_setup_regs(void)
 	 * Note that in the long run this should be done by clockfw
 	 */
 	cm_write_mod_reg(
+		OMAP3430_AUTO_MODEM |
 		OMAP3430ES2_AUTO_MMC3 |
 		OMAP3430ES2_AUTO_ICR |
 		OMAP3430_AUTO_AES2 |
@@ -474,7 +493,7 @@ static void __init prcm_setup_regs(void)
 		OMAP3430_AUTO_OMAPCTRL |
 		OMAP3430ES1_AUTO_FSHOSTUSB |
 		OMAP3430_AUTO_HSOTGUSB |
-		OMAP3430ES1_AUTO_D2D | /* This is es1 only */
+		OMAP3430_AUTO_SAD2D |
 		OMAP3430_AUTO_SSI,
 		CORE_MOD, CM_AUTOIDLE1);
 
@@ -488,6 +507,7 @@ static void __init prcm_setup_regs(void)
 
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
 		cm_write_mod_reg(
+			OMAP3430_AUTO_MAD2D |
 			OMAP3430ES2_AUTO_USBTLL,
 			CORE_MOD, CM_AUTOIDLE3);
 	}
@@ -581,6 +601,7 @@ static void __init prcm_setup_regs(void)
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
 	omap3_iva_idle();
+	omap3_d2d_idle();
 }
 
 static int __init pwrdms_setup(struct powerdomain *pwrdm)
diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h
index a9f05e5..fcc5a9b 100644
--- a/arch/arm/plat-omap/include/mach/control.h
+++ b/arch/arm/plat-omap/include/mach/control.h
@@ -144,6 +144,10 @@
 #define OMAP343X_CONTROL_PBIAS_LITE	(OMAP2_CONTROL_GENERAL + 0x02b0)
 #define OMAP343X_CONTROL_TEMP_SENSOR	(OMAP2_CONTROL_GENERAL + 0x02b4)
 
+/* 34xx D2D idle-related pins, handled by PM core */
+#define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
+#define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/13] OMAP3: PM: D2D clockdomain supports SW supervised transitions
  2009-05-20 23:19               ` [PATCH 08/13] OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init Kevin Hilman
@ 2009-05-20 23:19                 ` Kevin Hilman
  2009-05-20 23:19                   ` [PATCH 10/13] OMAP3: PM: Ensure MUSB block can idle when driver not loaded Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/clockdomains.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index 281d5da..fe319ae 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -195,7 +195,7 @@ static struct clockdomain sgx_clkdm = {
 static struct clockdomain d2d_clkdm = {
 	.name		= "d2d_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/13] OMAP3: PM: Ensure MUSB block can idle when driver not loaded
  2009-05-20 23:19                 ` [PATCH 09/13] OMAP3: PM: D2D clockdomain supports SW supervised transitions Kevin Hilman
@ 2009-05-20 23:19                   ` Kevin Hilman
  2009-05-20 23:19                     ` [PATCH 11/13] OMAP3: PM: Ensure PRCM interrupts are cleared at boot Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>

Otherwise, bootloaders may leave MUSB in a state which prevents
retention.

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/Makefile          |    2 --
 arch/arm/mach-omap2/usb-musb.c        |   20 ++++++++++++++++++++
 arch/arm/plat-omap/include/mach/usb.h |    6 ------
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index c8f1505..201214f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -60,9 +60,7 @@ obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
 					   mmc-twl4030.o
 
 # Platform specific device init code
-ifeq ($(CONFIG_USB_MUSB_SOC),y)
 obj-y					+= usb-musb.o
-endif
 
 onenand-$(CONFIG_MTD_ONENAND_OMAP2)	:= gpmc-onenand.o
 obj-y					+= $(onenand-m) $(onenand-y)
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 215d463..d85296d 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -31,6 +31,17 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
+#define OTG_SYSCONFIG	(OMAP34XX_HSUSB_OTG_BASE + 0x404)
+
+static void __init usb_musb_pm_init(void)
+{
+	/* Ensure force-idle mode for OTG controller */
+	if (cpu_is_omap34xx())
+		omap_writel(0, OTG_SYSCONFIG);
+}
+
+#ifdef CONFIG_USB_MUSB_SOC
+
 static struct resource musb_resources[] = {
 	[0] = { /* start and end set dynamically */
 		.flags	= IORESOURCE_MEM,
@@ -183,4 +194,13 @@ void __init usb_musb_init(void)
 		printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
 		return;
 	}
+
+	usb_musb_pm_init();
+}
+
+#else
+void __init usb_musb_init(void)
+{
+	usb_musb_pm_init();
 }
+#endif /* CONFIG_USB_MUSB_SOC */
diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h
index 69f0cee..f337e17 100644
--- a/arch/arm/plat-omap/include/mach/usb.h
+++ b/arch/arm/plat-omap/include/mach/usb.h
@@ -27,13 +27,7 @@
 #define UDC_BASE			OMAP2_UDC_BASE
 #define OMAP_OHCI_BASE			OMAP2_OHCI_BASE
 
-#ifdef CONFIG_USB_MUSB_SOC
 extern void usb_musb_init(void);
-#else
-static inline void usb_musb_init(void)
-{
-}
-#endif
 
 #endif
 
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/13] OMAP3: PM: Ensure PRCM interrupts are cleared at boot
  2009-05-20 23:19                   ` [PATCH 10/13] OMAP3: PM: Ensure MUSB block can idle when driver not loaded Kevin Hilman
@ 2009-05-20 23:19                     ` Kevin Hilman
  2009-05-20 23:19                       ` [PATCH 12/13] OMAP3: PM: Clear pending PRCM reset flags on init Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/pm34xx.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index d41e2c5..57d33f9 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -600,6 +600,9 @@ static void __init prcm_setup_regs(void)
 	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+	/* Clear any pending PRCM interrupts */
+	prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
 	omap3_iva_idle();
 	omap3_d2d_idle();
 }
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/13] OMAP3: PM: Clear pending PRCM reset flags on init
  2009-05-20 23:19                     ` [PATCH 11/13] OMAP3: PM: Ensure PRCM interrupts are cleared at boot Kevin Hilman
@ 2009-05-20 23:19                       ` Kevin Hilman
  2009-05-20 23:19                         ` [PATCH 13/13] OMAP3: PM: prevent module wakeups from waking IVA2 Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/pm34xx.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 57d33f9..8442286 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -600,6 +600,15 @@ static void __init prcm_setup_regs(void)
 	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+	/* Clear any pending 'reset' flags */
+	prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+
 	/* Clear any pending PRCM interrupts */
 	prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/13] OMAP3: PM: prevent module wakeups from waking IVA2
  2009-05-20 23:19                       ` [PATCH 12/13] OMAP3: PM: Clear pending PRCM reset flags on init Kevin Hilman
@ 2009-05-20 23:19                         ` Kevin Hilman
  0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-20 23:19 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

By default, prevent functional wakeups from inside a module from
waking up the IVA2.  Let DSP Bridge code handle this when loaded.

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/pm34xx.c |    6 ++++++
 arch/arm/mach-omap2/prm.h    |    2 ++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 8442286..deffafd 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -600,6 +600,12 @@ static void __init prcm_setup_regs(void)
 	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
 			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+	/* Don't attach IVA interrupts */
+	prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+	prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+
 	/* Clear any pending 'reset' flags */
 	prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
 	prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 7c8e0c4..9937e28 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -203,9 +203,11 @@
 
 #define OMAP3430_PM_MPUGRPSEL				0x00a4
 #define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
+#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
 
 #define OMAP3430_PM_IVAGRPSEL				0x00a8
 #define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
+#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
 
 #define OMAP3430_PM_PREPWSTST				0x00e8
 
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-20 23:19 ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kevin Hilman
  2009-05-20 23:19   ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Kevin Hilman
@ 2009-05-21 23:38   ` Kim Kyuwon
  2009-05-22 14:54     ` Kevin Hilman
  1 sibling, 1 reply; 26+ messages in thread
From: Kim Kyuwon @ 2009-05-21 23:38 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-arm-kernel, linux-omap

Kevin Hilman wrote:
> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
> 
> Adding a disable hook to the irq_chip is not the way to fix the
> problem being addressed by this patch.  Instead, we need to fix
> support for [enable|disable]_irq_wake().

Agree with you if we can use disable_irq_wake for MPU Interrupt with not 
masking the IRQ. Can you explain how we can fix support for 
disable_irq_wake() for omap_irq_chip?

> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
> ---
>  arch/arm/mach-omap2/irq.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
> index 998c5c4..08a3b99 100644
> --- a/arch/arm/mach-omap2/irq.c
> +++ b/arch/arm/mach-omap2/irq.c
> @@ -134,7 +134,6 @@ static struct irq_chip omap_irq_chip = {
>  	.ack	= omap_mask_ack_irq,
>  	.mask	= omap_mask_irq,
>  	.unmask	= omap_unmask_irq,
> -	.disable = omap_mask_irq,
>  };
>  
>  static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-21 23:38   ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kim Kyuwon
@ 2009-05-22 14:54     ` Kevin Hilman
  2009-05-22 15:51       ` Kim Kyuwon
  2009-05-22 23:22       ` Russell King - ARM Linux
  0 siblings, 2 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-22 14:54 UTC (permalink / raw)
  To: Kim Kyuwon; +Cc: linux-arm-kernel, linux-omap

Kim Kyuwon <q1.kim@samsung.com> writes:

> Kevin Hilman wrote:
>> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
>>
>> Adding a disable hook to the irq_chip is not the way to fix the
>> problem being addressed by this patch.  Instead, we need to fix
>> support for [enable|disable]_irq_wake().
>
> Agree with you if we can use disable_irq_wake for MPU Interrupt with
> not masking the IRQ. Can you explain how we can fix support for
> disable_irq_wake() for omap_irq_chip?

Yes.  The PRCM has a wake-enable per device bit that can be set (see
PM_WKEN_<pwrdm>) to control device wakeup enables.

But the implemenation of that should not hold up this revert because
this patch breaks *all* wakeups since the PRCM interrupt itself is
disabled in the suspend path.

As a workaround for your USB problem that this patch was initially
intended to fix you could manually disable USB OTG wakeups like this:

	wken = prm_read_mod_reg(CORE_MOD, PM_WKEN);
        wken &= ~OMAP3430_EN_HSOTGUSB; 
	prm_write_mod_reg(wken, CORE_MOD, PM_WKEN);
	
At least until the irq_wake stuff is fixed.

Kevin

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-22 14:54     ` Kevin Hilman
@ 2009-05-22 15:51       ` Kim Kyuwon
  2009-05-22 18:16         ` Kevin Hilman
  2009-05-22 23:22       ` Russell King - ARM Linux
  1 sibling, 1 reply; 26+ messages in thread
From: Kim Kyuwon @ 2009-05-22 15:51 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Kim Kyuwon, linux-arm-kernel, linux-omap

On Fri, May 22, 2009 at 11:54 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> Kim Kyuwon <q1.kim@samsung.com> writes:
>
>> Kevin Hilman wrote:
>>> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
>>>
>>> Adding a disable hook to the irq_chip is not the way to fix the
>>> problem being addressed by this patch.  Instead, we need to fix
>>> support for [enable|disable]_irq_wake().
>>
>> Agree with you if we can use disable_irq_wake for MPU Interrupt with
>> not masking the IRQ. Can you explain how we can fix support for
>> disable_irq_wake() for omap_irq_chip?
>
> Yes.  The PRCM has a wake-enable per device bit that can be set (see
> PM_WKEN_<pwrdm>) to control device wakeup enables.

PM_WKEN_<pwrdm> is not entirely matched to each MPU interrupt.
If you want to use disable_irq_wake() with enabling PRCM_Interrupt,
you should disable all PM_WKEN_<pwrdm> bits.
And how can you make support of disable_irq_wake() for other MPU interrupts?

> But the implemenation of that should not hold up this revert because
> this patch breaks *all* wakeups since the PRCM interrupt itself is
> disabled in the suspend path.

Yes, I saw the same problem. This is caused by resume_device_irqs()
recently added by Rafael not by my patch. I'm asking him that he made
a right decision.

> As a workaround for your USB problem that this patch was initially
> intended to fix you could manually disable USB OTG wakeups like this:
>
>        wken = prm_read_mod_reg(CORE_MOD, PM_WKEN);
>        wken &= ~OMAP3430_EN_HSOTGUSB;
>        prm_write_mod_reg(wken, CORE_MOD, PM_WKEN);

Did you checked this masking prevent waking up from the interrupt of USB HOST?

Regards,
Kyuwon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling  interrupts, v2"
  2009-05-22 15:51       ` Kim Kyuwon
@ 2009-05-22 18:16         ` Kevin Hilman
  2009-05-22 22:59           ` Kim Kyuwon
  2009-05-25  5:33           ` Kim Kyuwon
  0 siblings, 2 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-22 18:16 UTC (permalink / raw)
  To: Kim Kyuwon; +Cc: Kim Kyuwon, linux-arm-kernel, linux-omap

Kim Kyuwon <chammoru@gmail.com> writes:

> On Fri, May 22, 2009 at 11:54 PM, Kevin Hilman
> <khilman@deeprootsystems.com> wrote:
>> Kim Kyuwon <q1.kim@samsung.com> writes:
>>
>>> Kevin Hilman wrote:
>>>> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
>>>>
>>>> Adding a disable hook to the irq_chip is not the way to fix the
>>>> problem being addressed by this patch.  Instead, we need to fix
>>>> support for [enable|disable]_irq_wake().
>>>
>>> Agree with you if we can use disable_irq_wake for MPU Interrupt with
>>> not masking the IRQ. Can you explain how we can fix support for
>>> disable_irq_wake() for omap_irq_chip?
>>
>> Yes.  The PRCM has a wake-enable per device bit that can be set (see
>> PM_WKEN_<pwrdm>) to control device wakeup enables.
>
> PM_WKEN_<pwrdm> is not entirely matched to each MPU interrupt.

Correct.  This bit disables the module from generating any wakeup
event to the PRCM.

> If you want to use disable_irq_wake() with enabling PRCM_Interrupt,
> you should disable all PM_WKEN_<pwrdm> bits.
> And how can you make support of disable_irq_wake() for other MPU interrupts?

To control the ability of a module to wake the MPU directly, we would
need to use the PM_MPUGRPSEL_<pwrdm> regs.

>> But the implemenation of that should not hold up this revert because
>> this patch breaks *all* wakeups since the PRCM interrupt itself is
>> disabled in the suspend path.
>
> Yes, I saw the same problem. This is caused by resume_device_irqs()
> recently added by Rafael not by my patch. 

The point is, with your patch applied, *all* OMAP wakeups are broken
upstream.

You're right, your patch didn't cause the broken wakeup problem by
itself, but your patch on top of Rafael's in combination with the new
lazy-disable support which are both already in mainline breaks *all*
OMAP wakeup capabilities.  Therefore it should be reverted and the
OMAP specific IRQ wake support fixed.

I am working on fixing the OMAP IRQ wake support, but I do not want
that to hold up this series getting upstream.

> I'm asking him that he made a right decision.

Yes, we had a long discussion on that on linux-pm and I came to the
conclusion that while his change was probably premature, it's the
right decision and platforms with wakeup capabilities should
use/fix their set_irq_wakeup() functionality.

>> As a workaround for your USB problem that this patch was initially
>> intended to fix you could manually disable USB OTG wakeups like this:
>>
>>        wken = prm_read_mod_reg(CORE_MOD, PM_WKEN);
>>        wken &= ~OMAP3430_EN_HSOTGUSB;
>>        prm_write_mod_reg(wken, CORE_MOD, PM_WKEN);
>
> Did you checked this masking prevent waking up from the interrupt of USB HOST?

No I did not test, nor was I able to reproduce your original problem
since the description wasn't that clear to me.

This will disable the USB OTG controller module from generating
wakeups for any reason.  If disabling the device wakeup in PM_WKEN is
still resutling in interrupts, then the powerdomain with that device
is most likely not in retention/off.

I do know that disabling PM_WKEN for UARTs in the same powerdomain as
USB OTG (CORE) will stop the UART from waking, and thus from
generating interrupts, as long as the powerdomain has actually
transitioned to retention/off.

Re: USB HOST.  The problem you reported in your original patch was
that you were waking from IRQ 92, which is the USB OTG interrupt.  If
your problem is with USBHOST, that is in a different powerdomain.

Kevin

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-22 18:16         ` Kevin Hilman
@ 2009-05-22 22:59           ` Kim Kyuwon
  2009-05-25  5:33           ` Kim Kyuwon
  1 sibling, 0 replies; 26+ messages in thread
From: Kim Kyuwon @ 2009-05-22 22:59 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Kim Kyuwon, linux-arm-kernel, linux-omap, Rafael J. Wysocki

On Sat, May 23, 2009 at 3:16 AM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> Kim Kyuwon <chammoru@gmail.com> writes:
>
>> On Fri, May 22, 2009 at 11:54 PM, Kevin Hilman
>> <khilman@deeprootsystems.com> wrote:
>>> Kim Kyuwon <q1.kim@samsung.com> writes:
>>>
>>>> Kevin Hilman wrote:
>>>>> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
>>>>>
>>>>> Adding a disable hook to the irq_chip is not the way to fix the
>>>>> problem being addressed by this patch.  Instead, we need to fix
>>>>> support for [enable|disable]_irq_wake().
>>>>
>>>> Agree with you if we can use disable_irq_wake for MPU Interrupt with
>>>> not masking the IRQ. Can you explain how we can fix support for
>>>> disable_irq_wake() for omap_irq_chip?
>>>
>>> Yes.  The PRCM has a wake-enable per device bit that can be set (see
>>> PM_WKEN_<pwrdm>) to control device wakeup enables.
>>
>> PM_WKEN_<pwrdm> is not entirely matched to each MPU interrupt.
>
> Correct.  This bit disables the module from generating any wakeup
> event to the PRCM.
>
>> If you want to use disable_irq_wake() with enabling PRCM_Interrupt,
>> you should disable all PM_WKEN_<pwrdm> bits.
>> And how can you make support of disable_irq_wake() for other MPU interrupts?
>
> To control the ability of a module to wake the MPU directly, we would
> need to use the PM_MPUGRPSEL_<pwrdm> regs.

Sorry but I can't believe until it is implemented in OMAP and I can confirm it.

>>> But the implemenation of that should not hold up this revert because
>>> this patch breaks *all* wakeups since the PRCM interrupt itself is
>>> disabled in the suspend path.
>>
>> Yes, I saw the same problem. This is caused by resume_device_irqs()
>> recently added by Rafael not by my patch.
>
> The point is, with your patch applied, *all* OMAP wakeups are broken
> upstream.
>
> You're right, your patch didn't cause the broken wakeup problem by
> itself, but your patch on top of Rafael's in combination with the new
> lazy-disable support which are both already in mainline breaks *all*
> OMAP wakeup capabilities.  Therefore it should be reverted and the
> OMAP specific IRQ wake support fixed.
>
> I am working on fixing the OMAP IRQ wake support, but I do not want
> that to hold up this series getting upstream.

However, we don't know yet OMAP IRQ wake support is well implemented or not.

>> I'm asking him that he made a right decision.
>
> Yes, we had a long discussion on that on linux-pm and I came to the
> conclusion that while his change was probably premature, it's the
> right decision and platforms with wakeup capabilities should
> use/fix their set_irq_wakeup() functionality.

I know... I jumped into that discussion. But you insisted as following...
--
> Interrupt wakeups can be disabled at the PRCM level.  Or more simply
> we can keep a mask of wakeup-enable interrupts and use that.

> I will experiment with getting disable_irq_wake() working.
--
So I quited. But I think we should have this discussion again.

>>> As a workaround for your USB problem that this patch was initially
>>> intended to fix you could manually disable USB OTG wakeups like this:
>>>
>>>        wken = prm_read_mod_reg(CORE_MOD, PM_WKEN);
>>>        wken &= ~OMAP3430_EN_HSOTGUSB;
>>>        prm_write_mod_reg(wken, CORE_MOD, PM_WKEN);
>>
>> Did you checked this masking prevent waking up from the interrupt of USB HOST?
>
> No I did not test, nor was I able to reproduce your original problem
> since the description wasn't that clear to me.
>
> This will disable the USB OTG controller module from generating
> wakeups for any reason.  If disabling the device wakeup in PM_WKEN is
> still resutling in interrupts, then the powerdomain with that device
> is most likely not in retention/off.
>
> I do know that disabling PM_WKEN for UARTs in the same powerdomain as
> USB OTG (CORE) will stop the UART from waking, and thus from
> generating interrupts, as long as the powerdomain has actually
> transitioned to retention/off.
>
> Re: USB HOST.  The problem you reported in your original patch was
> that you were waking from IRQ 92, which is the USB OTG interrupt.  If
> your problem is with USBHOST, that is in a different powerdomain.

OK I will check it when I'm in my office. Now it's great weekend.
Have a good weekend!.

Regards,
Kyuwon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-22 14:54     ` Kevin Hilman
  2009-05-22 15:51       ` Kim Kyuwon
@ 2009-05-22 23:22       ` Russell King - ARM Linux
  2009-05-23  0:47         ` Kim Kyuwon
  1 sibling, 1 reply; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-05-22 23:22 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Kim Kyuwon, linux-arm-kernel, linux-omap

On Fri, May 22, 2009 at 07:54:32AM -0700, Kevin Hilman wrote:
> But the implemenation of that should not hold up this revert because
> this patch breaks *all* wakeups since the PRCM interrupt itself is
> disabled in the suspend path.

That is not mentioned in the patch description (and it should be).
What this paragraph is saying is that this revert is most definitely
fixing a regression.

Any "fix" which causes other breakage is not a fix, and therefore
this revert needs to go in no matter what.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-22 23:22       ` Russell King - ARM Linux
@ 2009-05-23  0:47         ` Kim Kyuwon
  0 siblings, 0 replies; 26+ messages in thread
From: Kim Kyuwon @ 2009-05-23  0:47 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Kevin Hilman, Kim Kyuwon, linux-arm-kernel, linux-omap

On Sat, May 23, 2009 at 8:22 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, May 22, 2009 at 07:54:32AM -0700, Kevin Hilman wrote:
>> But the implemenation of that should not hold up this revert because
>> this patch breaks *all* wakeups since the PRCM interrupt itself is
>> disabled in the suspend path.
>
> That is not mentioned in the patch description (and it should be).
> What this paragraph is saying is that this revert is most definitely
> fixing a regression.
>
> Any "fix" which causes other breakage is not a fix, and therefore
> this revert needs to go in no matter what.

The problem is that this patch(which is written by me) was merged much
earlier than Rafael's patch. So I think Rafael's patch causes other
breakage.

> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



-- 
Kyuwon (규원)
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
  2009-05-22 18:16         ` Kevin Hilman
  2009-05-22 22:59           ` Kim Kyuwon
@ 2009-05-25  5:33           ` Kim Kyuwon
  1 sibling, 0 replies; 26+ messages in thread
From: Kim Kyuwon @ 2009-05-25  5:33 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Kim Kyuwon, linux-arm-kernel, linux-omap

On Sat, May 23, 2009 at 3:16 AM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> Kim Kyuwon <chammoru@gmail.com> writes:
>
>> On Fri, May 22, 2009 at 11:54 PM, Kevin Hilman
>> <khilman@deeprootsystems.com> wrote:
>>> Kim Kyuwon <q1.kim@samsung.com> writes:
>>>
>>>> Kevin Hilman wrote:
>>>>> This reverts commit 5461af5af5c6a7fee78978aafe720541bf3a2f55.
>>>>>
>>>>> Adding a disable hook to the irq_chip is not the way to fix the
>>>>> problem being addressed by this patch.  Instead, we need to fix
>>>>> support for [enable|disable]_irq_wake().
>>>>
>>>> Agree with you if we can use disable_irq_wake for MPU Interrupt with
>>>> not masking the IRQ. Can you explain how we can fix support for
>>>> disable_irq_wake() for omap_irq_chip?
>>>
>>> Yes.  The PRCM has a wake-enable per device bit that can be set (see
>>> PM_WKEN_<pwrdm>) to control device wakeup enables.
>>
>> PM_WKEN_<pwrdm> is not entirely matched to each MPU interrupt.
>
> Correct.  This bit disables the module from generating any wakeup
> event to the PRCM.
>
>> If you want to use disable_irq_wake() with enabling PRCM_Interrupt,
>> you should disable all PM_WKEN_<pwrdm> bits.
>> And how can you make support of disable_irq_wake() for other MPU interrupts?
>
> To control the ability of a module to wake the MPU directly, we would
> need to use the PM_MPUGRPSEL_<pwrdm> regs.

PM_MPUGRPSEL_<pwrdm> regs can't disable irq wakeup, it is just related
wake-up dependencies.
I tested with this code:

prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
prm_write_mod_reg(0, MPU_MOD, OMAP3430_PM_MPUGRPSEL);
prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_MPUGRPSEL);
prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);

But USB interrupt have continuously woken up the system.
I checked with my omap wakeup source driver and wake-up source was shown below

# cat /sys/power/omap_resume_irq
92

>>> But the implemenation of that should not hold up this revert because
>>> this patch breaks *all* wakeups since the PRCM interrupt itself is
>>> disabled in the suspend path.
>>
>> Yes, I saw the same problem. This is caused by resume_device_irqs()
>> recently added by Rafael not by my patch.
>
> The point is, with your patch applied, *all* OMAP wakeups are broken
> upstream.
>
> You're right, your patch didn't cause the broken wakeup problem by
> itself, but your patch on top of Rafael's in combination with the new
> lazy-disable support which are both already in mainline breaks *all*
> OMAP wakeup capabilities.  Therefore it should be reverted and the
> OMAP specific IRQ wake support fixed.
>
> I am working on fixing the OMAP IRQ wake support, but I do not want
> that to hold up this series getting upstream.
>
>> I'm asking him that he made a right decision.
>
> Yes, we had a long discussion on that on linux-pm and I came to the
> conclusion that while his change was probably premature, it's the
> right decision and platforms with wakeup capabilities should
> use/fix their set_irq_wakeup() functionality.
>
>>> As a workaround for your USB problem that this patch was initially
>>> intended to fix you could manually disable USB OTG wakeups like this:
>>>
>>>        wken = prm_read_mod_reg(CORE_MOD, PM_WKEN);
>>>        wken &= ~OMAP3430_EN_HSOTGUSB;
>>>        prm_write_mod_reg(wken, CORE_MOD, PM_WKEN);

I also confirmed this code can't help disabling interrupt wakeup.

>> Did you checked this masking prevent waking up from the interrupt of USB HOST?
>
> No I did not test, nor was I able to reproduce your original problem
> since the description wasn't that clear to me.
>
> This will disable the USB OTG controller module from generating
> wakeups for any reason.  If disabling the device wakeup in PM_WKEN is
> still resutling in interrupts, then the powerdomain with that device
> is most likely not in retention/off.
>
> I do know that disabling PM_WKEN for UARTs in the same powerdomain as
> USB OTG (CORE) will stop the UART from waking, and thus from
> generating interrupts, as long as the powerdomain has actually
> transitioned to retention/off.
>
> Re: USB HOST.  The problem you reported in your original patch was
> that you were waking from IRQ 92, which is the USB OTG interrupt.  If
> your problem is with USBHOST, that is in a different powerdomain.
>
> Kevin
>
>

Kevin,

I'm terribly sorry to hold up your work. I will not disturb you
anymore in relation to this revert patch. However, please keep in mind
that adding a disable hook to the irq_chip was the best way to fix the
problem addressed by my original patch.

Regards,
Kyuwon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2 00/13] OMAP2/3: PM sync-up
  2009-05-20 23:19 [PATCH v2 00/13] OMAP2/3: PM sync-up Kevin Hilman
  2009-05-20 23:19 ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kevin Hilman
@ 2009-05-26 23:12 ` Tony Lindgren
  1 sibling, 0 replies; 26+ messages in thread
From: Tony Lindgren @ 2009-05-26 23:12 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-arm-kernel, linux-omap

* Kevin Hilman <khilman@deeprootsystems.com> [090520 16:20]:
> This series is intended to push the core PM support from linux-omap
> into mainline.  
> 
> Upon review/acceptance, Tony will merge into his for-next branch for
> the next merge window so all OMAP stuff can come from one place.
> 
> In addition to the linux-omap PM core sync, several OMAP3 init fixes
> are required to ensure that the chip can hit full-chip retention on
> idle and suspend.
> 
> Currently based on Tony's omap3-upstream branch.  Compile tested on
> OMAP2, Boot tested on OMAP3430SDP and can hit full-chip retention in
> suspend and in idle.

I've pulled these to omap for-next branch.

Tony
 
> Changes since v1:
>  - updated "push core PM" patch with review comments
>    - dropped all /sys/power/* knobs
>    - will use hlt_counter when it's exported to platform code
>    - dropped save/restore of abort mode regs in favor of cpu_init()
>  - MUSB idle patch fixed to work even when MUSB not enabled in Kconfig
>  - 2 new patches
>    - added UART-specific timeout feature under uart platform device.
>      this replaces the need for /sys/power/clocks_off_while_idle   
>    - revert of irq_chip->disable patch which is the wrong solution
>      for the bug it was trying to fix
> 
> Jouni Hogander (2):
>   OMAP: Add new function to check wether there is irq pending
>   OMAP: UART: Add sysfs interface for adjusting UART sleep timeout
> 
> Kevin Hilman (10):
>   Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2"
>   OMAP2/3: PM: push core PM code from linux-omap
>   OMAP3: PM: Force IVA2 into idle during bootup
>   OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X
>   OMAP3: PM: UART: disable clocks when idle and off-mode support
>   OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init
>   OMAP3: PM: D2D clockdomain supports SW supervised transitions
>   OMAP3: PM: Ensure PRCM interrupts are cleared at boot
>   OMAP3: PM: Clear pending PRCM reset flags on init
>   OMAP3: PM: prevent module wakeups from waking IVA2
> 
> Peter 'p2' De Schrijver (1):
>   OMAP3: PM: Ensure MUSB block can idle when driver not loaded
> 
>  arch/arm/mach-omap2/Makefile              |    5 +-
>  arch/arm/mach-omap2/clock34xx.c           |    3 +
>  arch/arm/mach-omap2/clock34xx.h           |   33 ++-
>  arch/arm/mach-omap2/clockdomains.h        |    2 +-
>  arch/arm/mach-omap2/cm-regbits-34xx.h     |   14 +
>  arch/arm/mach-omap2/irq.c                 |   18 +-
>  arch/arm/mach-omap2/pm-debug.c            |  152 ++++++
>  arch/arm/mach-omap2/pm.c                  |  134 +++----
>  arch/arm/mach-omap2/pm.h                  |   40 ++
>  arch/arm/mach-omap2/pm24xx.c              |  549 ++++++++++++++++++++++
>  arch/arm/mach-omap2/pm34xx.c              |  710 +++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/prcm-common.h         |    2 +
>  arch/arm/mach-omap2/prm.h                 |    2 +
>  arch/arm/mach-omap2/sdrc.c                |    5 +-
>  arch/arm/mach-omap2/serial.c              |  437 +++++++++++++++++-
>  arch/arm/mach-omap2/sleep24xx.S           |    1 -
>  arch/arm/mach-omap2/sleep34xx.S           |  436 ++++++++++++++++++
>  arch/arm/mach-omap2/usb-musb.c            |   21 +-
>  arch/arm/plat-omap/Kconfig                |    2 +-
>  arch/arm/plat-omap/common.c               |    1 -
>  arch/arm/plat-omap/include/mach/common.h  |    2 -
>  arch/arm/plat-omap/include/mach/control.h |   13 +
>  arch/arm/plat-omap/include/mach/irqs.h    |    1 +
>  arch/arm/plat-omap/include/mach/pm.h      |  345 --------------
>  arch/arm/plat-omap/include/mach/serial.h  |    9 +
>  arch/arm/plat-omap/include/mach/usb.h     |    6 -
>  drivers/mtd/onenand/omap2.c               |    1 -
>  27 files changed, 2475 insertions(+), 469 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/pm-debug.c
>  create mode 100644 arch/arm/mach-omap2/pm.h
>  create mode 100644 arch/arm/mach-omap2/pm24xx.c
>  create mode 100644 arch/arm/mach-omap2/pm34xx.c
>  create mode 100644 arch/arm/mach-omap2/sleep34xx.S
>  delete mode 100644 arch/arm/plat-omap/include/mach/pm.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap
  2009-05-20 23:19   ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Kevin Hilman
  2009-05-20 23:19     ` [PATCH 03/13] OMAP: Add new function to check wether there is irq pending Kevin Hilman
@ 2009-05-28 15:48     ` Russell King - ARM Linux
  2009-05-28 16:51       ` Kevin Hilman
  1 sibling, 1 reply; 26+ messages in thread
From: Russell King - ARM Linux @ 2009-05-28 15:48 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-arm-kernel, linux-omap

On Wed, May 20, 2009 at 04:19:25PM -0700, Kevin Hilman wrote:
> This patch is to sync the core linux-omap PM code with mainline.  This
> code has evolved and been used for a while the linux-omap tree, but
> the attempt here is to finally get this into mainline.

Hmm..

> +static int __init omap_pm_init(void)
>  {
> -	return 0;
> +	int error = -1;
> +
> +	if (cpu_is_omap24xx())
> +		error = omap2_pm_init();
> +	if (cpu_is_omap34xx())
> +		error = omap3_pm_init();

Experience with PXA has shown that this tends to be the wrong way up
of doing things.  It seems to be much better to have the SoC specific
code call the SoC generic code instead.

So, eg, omap2_pm_init() becomes:

static int omap2_pm_init(void)
{
	if (!cpu_is_omap24xx())
		return -ENODEV;

	... omap24xx initialisation ...

	return omap_pm_init();
}
late_initcall(omap2_pm_init);

(and, since this is always built-in, there's no point doing cleanup if
omap_pm_init() fails - you're not going to be able to re-run that
initialization again.)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap
  2009-05-28 15:48     ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Russell King - ARM Linux
@ 2009-05-28 16:51       ` Kevin Hilman
  2009-05-28 18:22         ` Kevin Hilman
  0 siblings, 1 reply; 26+ messages in thread
From: Kevin Hilman @ 2009-05-28 16:51 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap

Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Wed, May 20, 2009 at 04:19:25PM -0700, Kevin Hilman wrote:
>> This patch is to sync the core linux-omap PM code with mainline.  This
>> code has evolved and been used for a while the linux-omap tree, but
>> the attempt here is to finally get this into mainline.
>
> Hmm..
>
>> +static int __init omap_pm_init(void)
>>  {
>> -	return 0;
>> +	int error = -1;
>> +
>> +	if (cpu_is_omap24xx())
>> +		error = omap2_pm_init();
>> +	if (cpu_is_omap34xx())
>> +		error = omap3_pm_init();
>
> Experience with PXA has shown that this tends to be the wrong way up
> of doing things.  It seems to be much better to have the SoC specific
> code call the SoC generic code instead.

OK.

> So, eg, omap2_pm_init() becomes:
>
> static int omap2_pm_init(void)
> {
> 	if (!cpu_is_omap24xx())
> 		return -ENODEV;
>
> 	... omap24xx initialisation ...
>
> 	return omap_pm_init();
> }
> late_initcall(omap2_pm_init);
>
> (and, since this is always built-in, there's no point doing cleanup if
> omap_pm_init() fails - you're not going to be able to re-run that
> initialization again.)

Sounds good, I'll make this change and upate the pm-upstream branch
for Tony.

This will leave the common omap_pm_init() and pm.c basically empty, so
I'll just remove them.

Kevin

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap
  2009-05-28 16:51       ` Kevin Hilman
@ 2009-05-28 18:22         ` Kevin Hilman
  0 siblings, 0 replies; 26+ messages in thread
From: Kevin Hilman @ 2009-05-28 18:22 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap

Kevin Hilman <khilman@deeprootsystems.com> writes:

> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>
>> On Wed, May 20, 2009 at 04:19:25PM -0700, Kevin Hilman wrote:
>>> This patch is to sync the core linux-omap PM code with mainline.  This
>>> code has evolved and been used for a while the linux-omap tree, but
>>> the attempt here is to finally get this into mainline.
>>
>> Hmm..
>>
>>> +static int __init omap_pm_init(void)
>>>  {
>>> -	return 0;
>>> +	int error = -1;
>>> +
>>> +	if (cpu_is_omap24xx())
>>> +		error = omap2_pm_init();
>>> +	if (cpu_is_omap34xx())
>>> +		error = omap3_pm_init();
>>
>> Experience with PXA has shown that this tends to be the wrong way up
>> of doing things.  It seems to be much better to have the SoC specific
>> code call the SoC generic code instead.
>
> OK.
>
>> So, eg, omap2_pm_init() becomes:
>>
>> static int omap2_pm_init(void)
>> {
>> 	if (!cpu_is_omap24xx())
>> 		return -ENODEV;
>>
>> 	... omap24xx initialisation ...
>>
>> 	return omap_pm_init();
>> }
>> late_initcall(omap2_pm_init);
>>
>> (and, since this is always built-in, there's no point doing cleanup if
>> omap_pm_init() fails - you're not going to be able to re-run that
>> initialization again.)
>
> Sounds good, I'll make this change and upate the pm-upstream branch
> for Tony.
>
> This will leave the common omap_pm_init() and pm.c basically empty, so
> I'll just remove them.

OK, pushed an updated version of this patch into a new pm-upstream branch
of my omap-pm tree[1]

Kevin

[1] http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-05-28 18:22 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-20 23:19 [PATCH v2 00/13] OMAP2/3: PM sync-up Kevin Hilman
2009-05-20 23:19 ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kevin Hilman
2009-05-20 23:19   ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Kevin Hilman
2009-05-20 23:19     ` [PATCH 03/13] OMAP: Add new function to check wether there is irq pending Kevin Hilman
2009-05-20 23:19       ` [PATCH 04/13] OMAP3: PM: Force IVA2 into idle during bootup Kevin Hilman
2009-05-20 23:19         ` [PATCH 05/13] OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X Kevin Hilman
2009-05-20 23:19           ` [PATCH 06/13] OMAP3: PM: UART: disable clocks when idle and off-mode support Kevin Hilman
2009-05-20 23:19             ` [PATCH 07/13] OMAP: UART: Add sysfs interface for adjusting UART sleep timeout Kevin Hilman
2009-05-20 23:19               ` [PATCH 08/13] OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init Kevin Hilman
2009-05-20 23:19                 ` [PATCH 09/13] OMAP3: PM: D2D clockdomain supports SW supervised transitions Kevin Hilman
2009-05-20 23:19                   ` [PATCH 10/13] OMAP3: PM: Ensure MUSB block can idle when driver not loaded Kevin Hilman
2009-05-20 23:19                     ` [PATCH 11/13] OMAP3: PM: Ensure PRCM interrupts are cleared at boot Kevin Hilman
2009-05-20 23:19                       ` [PATCH 12/13] OMAP3: PM: Clear pending PRCM reset flags on init Kevin Hilman
2009-05-20 23:19                         ` [PATCH 13/13] OMAP3: PM: prevent module wakeups from waking IVA2 Kevin Hilman
2009-05-28 15:48     ` [PATCH 02/13] OMAP2/3: PM: push core PM code from linux-omap Russell King - ARM Linux
2009-05-28 16:51       ` Kevin Hilman
2009-05-28 18:22         ` Kevin Hilman
2009-05-21 23:38   ` [PATCH 01/13] Revert "ARM: OMAP: Mask interrupts when disabling interrupts, v2" Kim Kyuwon
2009-05-22 14:54     ` Kevin Hilman
2009-05-22 15:51       ` Kim Kyuwon
2009-05-22 18:16         ` Kevin Hilman
2009-05-22 22:59           ` Kim Kyuwon
2009-05-25  5:33           ` Kim Kyuwon
2009-05-22 23:22       ` Russell King - ARM Linux
2009-05-23  0:47         ` Kim Kyuwon
2009-05-26 23:12 ` [PATCH v2 00/13] OMAP2/3: PM sync-up Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox