Merge remote branches 'remotes/origin/pwrdm_clkdm_b_2.6.39', 'remotes/origin/pwrdm_add_can_lose_context_fns_2.6.39', 'remotes/origin/omap_device_a_2.6.39', 'remotes/origin/mmc_a_2.6.39', 'remotes/origin/hwmod_b_2.6.39', 'remotes/origin/dmtimer_a_2.6.39', 'remotes/origin/pwrdm_clkdm_a_2.6.39', 'remotes/origin/clkdm_statdep_omap4_2.6.39', 'remotes/origin/clk_a_2.6.39', 'remotes/origin/clk_autoidle_a_2.6.39', 'remotes/origin/clk_autoidle_b_2.6.39', 'remotes/origin/clk_b_2.6.39', 'remotes/origin/clk_clkdm_a_2.6.39', 'remotes/origin/misc_a_2.6.39', 'remotes/origin/for_2.6.39/omap3_hwmod_data' and 'remotes/origin/wdtimer_a_2.6.39' into tmp-integration-2.6.39-20110310-024
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index e68f6c0..d9af981 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -136,6 +136,8 @@
 	},
 };
 
+#define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
 	{
 		.ops		= &omap1_mcbsp_ops,
@@ -147,7 +149,7 @@
 #define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
 #define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
 #else
-#define omap7xx_mcbsp_res		NULL
+#define omap7xx_mcbsp_res_0		NULL
 #define omap7xx_mcbsp_pdata		NULL
 #define OMAP7XX_MCBSP_RES_SZ		0
 #define OMAP7XX_MCBSP_COUNT		0
@@ -238,6 +240,8 @@
 	},
 };
 
+#define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 	{
 		.ops		= &omap1_mcbsp_ops,
@@ -252,7 +256,7 @@
 #define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
 #define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
 #else
-#define omap15xx_mcbsp_res		NULL
+#define omap15xx_mcbsp_res_0		NULL
 #define omap15xx_mcbsp_pdata		NULL
 #define OMAP15XX_MCBSP_RES_SZ		0
 #define OMAP15XX_MCBSP_COUNT		0
@@ -343,6 +347,8 @@
 	},
 };
 
+#define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 	{
 		.ops		= &omap1_mcbsp_ops,
@@ -357,7 +363,7 @@
 #define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
 #define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
 #else
-#define omap16xx_mcbsp_res		NULL
+#define omap16xx_mcbsp_res_0		NULL
 #define omap16xx_mcbsp_pdata		NULL
 #define OMAP16XX_MCBSP_RES_SZ		0
 #define OMAP16XX_MCBSP_COUNT		0
@@ -381,19 +387,19 @@
 		return -ENOMEM;
 
 	if (cpu_is_omap7xx())
-		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res[0],
+		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
 					OMAP7XX_MCBSP_RES_SZ,
 					omap7xx_mcbsp_pdata,
 					OMAP7XX_MCBSP_COUNT);
 
 	if (cpu_is_omap15xx())
-		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res[0],
+		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
 					OMAP15XX_MCBSP_RES_SZ,
 					omap15xx_mcbsp_pdata,
 					OMAP15XX_MCBSP_COUNT);
 
 	if (cpu_is_omap16xx())
-		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res[0],
+		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
 					OMAP16XX_MCBSP_RES_SZ,
 					omap16xx_mcbsp_pdata,
 					OMAP16XX_MCBSP_COUNT);
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 1c3635d..534d89a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -102,25 +102,31 @@
 
 # PRCM clockdomain control
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
+					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
+
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o \
 					   clkt2xxx_sys.o \
 					   clkt2xxx_dpllcore.o \
 					   clkt2xxx_virt_prcm_set.o \
-					   clkt2xxx_apll.o clkt2xxx_osc.o
+					   clkt2xxx_apll.o clkt2xxx_osc.o \
+					   clkt2xxx_dpll.o clkt_iclk.o
 obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o clock2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o \
 					   clock34xx.o clkt34xx_dpll3m2.o \
 					   clock3517.o clock36xx.o \
-					   dpll3xxx.o clock3xxx_data.o
+					   dpll3xxx.o clock3xxx_data.o \
+					   clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) clock44xx_data.o \
-					   dpll3xxx.o
+					   dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
@@ -135,6 +141,10 @@
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
 
+# L3 interconnect
+obj-$(CONFIG_ARCH_OMAP3)		+= omap_l3_smx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= omap_l3_noc.o
+
 obj-$(CONFIG_OMAP_MBOX_FWK)		+= mailbox_mach.o
 mailbox_mach-objs			:= mailbox.o
 
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 30ec451..77541cf 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -200,6 +200,9 @@
 };
 static struct i2c_board_info __initdata am3517evm_i2c2_boardinfo[] = {
 	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1A),
+	},
+	{
 		I2C_BOARD_INFO("tca6416", 0x21),
 		.platform_data = &am3517evm_gpio_expander_info_0,
 	},
diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index f51cffd..b19a1f7 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -78,6 +78,26 @@
 	return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
 }
 
+static void _apll96_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_auto_low_power_stop();
+}
+
+static void _apll96_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_disable_autoidle();
+}
+
+static void _apll54_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_auto_low_power_stop();
+}
+
+static void _apll54_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_disable_autoidle();
+}
+
 /* Stop APLL */
 static void omap2_clk_apll_disable(struct clk *clk)
 {
@@ -93,11 +113,15 @@
 const struct clkops clkops_apll96 = {
 	.enable		= omap2_clk_apll96_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll96_allow_idle,
+	.deny_idle	= _apll96_deny_idle,
 };
 
 const struct clkops clkops_apll54 = {
 	.enable		= omap2_clk_apll54_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll54_allow_idle,
+	.deny_idle	= _apll54_deny_idle,
 };
 
 /* Public functions */
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c
new file mode 100644
index 0000000..1502a7b
--- /dev/null
+++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP2-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/**
+ * _allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control.  The DPLL will enter low-power
+ * stop when its downstream clocks are gated.  No return value.
+ * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
+ * instead.  Add some mechanism to optionally enter this mode.
+ */
+static void _allow_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_auto_low_power_stop();
+}
+
+/**
+ * _deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control.  No return value.
+ */
+static void _deny_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_disable_autoidle();
+}
+
+
+/* Public data */
+
+const struct clkops clkops_omap2xxx_dpll_ops = {
+	.allow_idle	= _allow_idle,
+	.deny_idle	= _deny_idle,
+};
+
diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
index df7b805..c346092 100644
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ b/arch/arm/mach-omap2/clkt2xxx_osc.c
@@ -30,6 +30,13 @@
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
+/*
+ * XXX This does not actually enable the osc_ck, since the osc_ck must
+ * be running for this function to be called.  Instead, this function
+ * is used to disable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static int omap2_enable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
@@ -41,6 +48,13 @@
 	return 0;
 }
 
+/*
+ * XXX This does not actually disable the osc_ck, since doing so would
+ * immediately halt the system.  Instead, this function is used to
+ * enable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static void omap2_disable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index acb7ae5..bcffee0 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -178,12 +178,11 @@
 	if (!dd)
 		return;
 
-	/* Return bypass rate if DPLL is bypassed */
 	v = __raw_readl(dd->control_reg);
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
-	/* Reparent in case the dpll is in bypass */
+	/* Reparent the struct clk in case the dpll is in bypass */
 	if (cpu_is_omap24xx()) {
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
@@ -260,50 +259,22 @@
 /* DPLL rate rounding code */
 
 /**
- * omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding
- * @clk: struct clk * of the DPLL
- * @tolerance: maximum rate error tolerance
- *
- * Set the maximum DPLL rate error tolerance for the rate rounding
- * algorithm.  The rate tolerance is an attempt to balance DPLL power
- * saving (the least divider value "n") vs. rate fidelity (the least
- * difference between the desired DPLL target rate and the rounded
- * rate out of the algorithm).  So, increasing the tolerance is likely
- * to decrease DPLL power consumption and increase DPLL rate error.
- * Returns -EINVAL if provided a null clock ptr or a clk that is not a
- * DPLL; or 0 upon success.
- */
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
-{
-	if (!clk || !clk->dpll_data)
-		return -EINVAL;
-
-	clk->dpll_data->rate_tolerance = tolerance;
-
-	return 0;
-}
-
-/**
  * omap2_dpll_round_rate - round a target rate for an OMAP DPLL
  * @clk: struct clk * for a DPLL
  * @target_rate: desired DPLL clock rate
  *
- * Given a DPLL, a desired target rate, and a rate tolerance, round
- * the target rate to a possible, programmable rate for this DPLL.
- * Rate tolerance is assumed to be set by the caller before this
- * function is called.  Attempts to select the minimum possible n
- * within the tolerance to reduce power consumption.  Stores the
- * computed (m, n) in the DPLL's dpll_data structure so set_rate()
- * will not need to call this (expensive) function again.  Returns ~0
- * if the target rate cannot be rounded, either because the rate is
- * too low or because the rate tolerance is set too tightly; or the
- * rounded rate upon success.
+ * Given a DPLL and a desired target rate, round the target rate to a
+ * possible, programmable rate for this DPLL.  Attempts to select the
+ * minimum possible n.  Stores the computed (m, n) in the DPLL's
+ * dpll_data structure so set_rate() will not need to call this
+ * (expensive) function again.  Returns ~0 if the target rate cannot
+ * be rounded, or the rounded rate upon success.
  */
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 {
-	int m, n, r, e, scaled_max_m;
-	unsigned long scaled_rt_rp, new_rate;
-	int min_e = -1, min_e_m = -1, min_e_n = -1;
+	int m, n, r, scaled_max_m;
+	unsigned long scaled_rt_rp;
+	unsigned long new_rate = 0;
 	struct dpll_data *dd;
 
 	if (!clk || !clk->dpll_data)
@@ -311,8 +282,8 @@
 
 	dd = clk->dpll_data;
 
-	pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
-		 "%ld\n", clk->name, target_rate);
+	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
+		 clk->name, target_rate);
 
 	scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
 	scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
@@ -347,39 +318,23 @@
 		if (r == DPLL_MULT_UNDERFLOW)
 			continue;
 
-		e = target_rate - new_rate;
-		pr_debug("clock: n = %d: m = %d: rate error is %d "
-			 "(new_rate = %ld)\n", n, m, e, new_rate);
+		pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
+			 clk->name, m, n, new_rate);
 
-		if (min_e == -1 ||
-		    min_e >= (int)(abs(e) - dd->rate_tolerance)) {
-			min_e = e;
-			min_e_m = m;
-			min_e_n = n;
-
-			pr_debug("clock: found new least error %d\n", min_e);
-
-			/* We found good settings -- bail out now */
-			if (min_e <= dd->rate_tolerance)
-				break;
+		if (target_rate == new_rate) {
+			dd->last_rounded_m = m;
+			dd->last_rounded_n = n;
+			dd->last_rounded_rate = target_rate;
+			break;
 		}
 	}
 
-	if (min_e < 0) {
-		pr_debug("clock: error: target rate or tolerance too low\n");
+	if (target_rate != new_rate) {
+		pr_debug("clock: %s: cannot round to rate %ld\n", clk->name,
+			 target_rate);
 		return ~0;
 	}
 
-	dd->last_rounded_m = min_e_m;
-	dd->last_rounded_n = min_e_n;
-	dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
-						       min_e_m,  min_e_n);
-
-	pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
-		 min_e, min_e_m, min_e_n);
-	pr_debug("clock: final rate: %ld  (target rate: %ld)\n",
-		 dd->last_rounded_rate, target_rate);
-
-	return dd->last_rounded_rate;
+	return target_rate;
 }
 
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
new file mode 100644
index 0000000..3d43fba
--- /dev/null
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -0,0 +1,82 @@
+/*
+ * OMAP2/3 interface clock control
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+#include <plat/prcm.h>
+
+#include "clock.h"
+#include "clock2xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/* XXX */
+void omap2_clkt_iclk_allow_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v |= (1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* XXX */
+void omap2_clkt_iclk_deny_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v &= ~(1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* Public data */
+
+const struct clkops clkops_omap2_iclk_dflt_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_companion	= omap2_clk_dflt_find_companion,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_dflt = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_idle_only = {
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_mdmclk_dflt_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_companion	= omap2_clk_dflt_find_companion,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 2a2f152..46d03cc 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -261,10 +261,11 @@
 
 	pr_debug("clock: %s: disabling in hardware\n", clk->name);
 
-	clk->ops->disable(clk);
+	if (clk->ops && clk->ops->disable)
+		clk->ops->disable(clk);
 
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -304,7 +305,7 @@
 	}
 
 	if (clk->clkdm) {
-		ret = omap2_clkdm_clk_enable(clk->clkdm, clk);
+		ret = clkdm_clk_enable(clk->clkdm, clk);
 		if (ret) {
 			WARN(1, "clock: %s: could not enable clockdomain %s: "
 			     "%d\n", clk->name, clk->clkdm->name, ret);
@@ -312,17 +313,20 @@
 		}
 	}
 
-	ret = clk->ops->enable(clk);
-	if (ret) {
-		WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret);
-		goto oce_err3;
+	if (clk->ops && clk->ops->enable) {
+		ret = clk->ops->enable(clk);
+		if (ret) {
+			WARN(1, "clock: %s: could not enable: %d\n",
+			     clk->name, ret);
+			goto oce_err3;
+		}
 	}
 
 	return 0;
 
 oce_err3:
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -373,11 +377,17 @@
 const struct clkops clkops_omap3_noncore_dpll_ops = {
 	.enable		= omap3_noncore_dpll_enable,
 	.disable	= omap3_noncore_dpll_disable,
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
+};
+
+const struct clkops clkops_omap3_core_dpll_ops = {
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
 };
 
 #endif
 
-
 /*
  * OMAP2+ clock reset and init functions
  */
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 896584e..e10ff2b 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -2,7 +2,7 @@
  *  linux/arch/arm/mach-omap2/clock.h
  *
  *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2009 Nokia Corporation
+ *  Copyright (C) 2004-2011 Nokia Corporation
  *
  *  Contacts:
  *  Richard Woodruff <r-woodruff2@ti.com>
@@ -18,9 +18,6 @@
 
 #include <plat/clock.h>
 
-/* The maximum error between a target DPLL rate and the rounded rate in Hz */
-#define DEFAULT_DPLL_RATE_TOLERANCE	50000
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K		0x0
 #define CORE_CLK_SRC_DPLL		0x1
@@ -55,7 +52,6 @@
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
 unsigned long omap3_dpll_recalc(struct clk *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk *clk);
@@ -65,6 +61,9 @@
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
 int omap3_noncore_dpll_enable(struct clk *clk);
 void omap3_noncore_dpll_disable(struct clk *clk);
+int omap4_dpllmx_gatectrl_read(struct clk *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
@@ -83,6 +82,10 @@
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
 
+/* clkt_iclk.c public functions */
+extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
+extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
+
 u32 omap2_get_dpll_rate(struct clk *clk);
 void omap2_init_dpll_parent(struct clk *clk);
 
@@ -136,6 +139,7 @@
 extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
+extern const struct clksel_rate dsp_ick_rates[];
 
 #if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
 extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
@@ -145,6 +149,13 @@
 #define omap2_clk_exit_cpufreq_table	0
 #endif
 
+extern const struct clkops clkops_omap2_iclk_dflt_wait;
+extern const struct clkops clkops_omap2_iclk_dflt;
+extern const struct clkops clkops_omap2_iclk_idle_only;
+extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
+extern const struct clkops clkops_omap2xxx_dpll_ops;
 extern const struct clkops clkops_omap3_noncore_dpll_ops;
+extern const struct clkops clkops_omap3_core_dpll_ops;
+extern const struct clkops clkops_omap4_dpllmx_ops;
 
 #endif
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 0a992bc8..b6f65d4 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2420_data.c
+ * OMAP2420 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
  *
  * 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
@@ -34,18 +34,15 @@
 /*
  * 2420 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -455,36 +451,22 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* 2420 only */
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -579,7 +561,7 @@
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,7 +643,7 @@
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -716,6 +698,7 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -763,7 +746,7 @@
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -825,6 +808,14 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -845,9 +836,9 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -871,7 +862,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -895,7 +886,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -919,7 +910,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -943,7 +934,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -967,7 +958,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -991,8 +982,9 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1014,7 +1006,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1038,7 +1030,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1062,7 +1054,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1086,7 +1078,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1110,7 +1102,7 @@
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1134,7 +1126,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1174,7 +1166,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1198,7 +1190,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1218,7 +1210,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1238,7 +1230,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1258,7 +1250,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1298,9 +1290,9 @@
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1318,9 +1310,9 @@
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1338,10 +1330,10 @@
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1349,9 +1341,9 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1359,10 +1351,10 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1370,7 +1362,7 @@
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1395,7 +1387,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1405,7 +1397,7 @@
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1425,7 +1417,7 @@
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1445,7 +1437,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1465,7 +1457,7 @@
 
 static struct clk mmc_ick = {
 	.name		= "mmc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1505,7 +1497,7 @@
 
 static struct clk eac_ick = {
 	.name		= "eac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1525,7 +1517,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1545,7 +1537,7 @@
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1565,7 +1557,7 @@
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1583,12 +1575,18 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1600,17 +1598,38 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
+	.recalc		= &followparent_recalc,
+};
+
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
+static struct clk sdrc_ick = {
+	.name		= "sdrc_ick",
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk vlynq_ick = {
 	.name		= "vlynq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1659,7 +1678,7 @@
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1688,7 @@
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1698,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1708,7 @@
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1718,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1777,7 +1796,6 @@
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_242X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_242X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_242X),
 	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
 	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
 	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
@@ -1797,6 +1815,7 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1869,6 +1888,7 @@
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_242X),
 	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
 	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
 	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
@@ -1913,6 +1933,9 @@
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 5c647ce..bba0183 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2430_data.c
+ * OMAP2430 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
  *
  * 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
@@ -34,18 +34,15 @@
 /*
  * 2430 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -434,37 +430,23 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
 /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -525,7 +507,7 @@
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -606,7 +588,7 @@
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,6 +643,7 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -693,7 +676,7 @@
 
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
@@ -706,7 +689,7 @@
 
 static struct clk mdm_osc_ck = {
 	.name		= "mdm_osc_ck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &osc_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
@@ -751,7 +734,7 @@
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -813,6 +796,14 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -833,9 +824,9 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -859,7 +850,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -883,7 +874,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -907,7 +898,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -931,7 +922,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -955,7 +946,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -979,8 +970,9 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1002,7 +994,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1026,7 +1018,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1050,7 +1042,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1074,7 +1066,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1098,7 +1090,7 @@
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1122,7 +1114,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1162,7 +1154,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1186,7 +1178,7 @@
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1210,7 +1202,7 @@
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1234,7 +1226,7 @@
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1258,7 +1250,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1298,7 +1290,7 @@
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1318,7 +1310,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1338,7 +1330,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1358,7 +1350,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1378,9 +1370,9 @@
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1398,9 +1390,9 @@
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1418,10 +1410,10 @@
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1429,9 +1421,9 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1439,10 +1431,10 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1450,9 +1442,9 @@
 
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1460,7 +1452,7 @@
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1495,7 +1487,7 @@
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1515,7 +1507,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1535,7 +1527,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1555,7 +1547,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1579,7 +1571,7 @@
  */
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1603,7 +1595,7 @@
  */
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1621,12 +1613,18 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1638,20 +1636,26 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1659,7 +1663,7 @@
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1673,7 @@
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1683,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1693,7 @@
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1703,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1719,7 +1723,7 @@
 
 static struct clk usbhs_ick = {
 	.name		= "usbhs_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1729,7 +1733,7 @@
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1741,7 +1745,7 @@
 	.name		= "mmchs1_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1749,7 +1753,7 @@
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1761,6 +1765,7 @@
 	.name		= "mmchs2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1768,7 +1773,7 @@
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1788,7 +1793,7 @@
 
 static struct clk mdm_intc_ick = {
 	.name		= "mdm_intc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1880,7 +1885,6 @@
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_243X),
 	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
 	/* GFX domain clocks */
 	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X),
@@ -1901,6 +1905,7 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -2028,6 +2033,9 @@
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 287abc4..1fc96b9 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -2,7 +2,7 @@
  * OMAP3-specific clock framework functions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  * Jouni Högander
@@ -59,6 +59,15 @@
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  * @clk: struct clk * being enabled
@@ -94,6 +103,15 @@
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  * @clk: struct clk * being enabled
@@ -124,3 +142,12 @@
 	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
 	.find_companion = omap2_clk_dflt_find_companion,
 };
+
+const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 628e8de..084ba71 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -2,14 +2,17 @@
  * OMAP34xx clock function prototypes and macros
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 
 extern const struct clkops clkops_omap3430es2_ssi_wait;
+extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
 extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
+extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
+extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
 
 #endif
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
index 74116a3..2e97d08 100644
--- a/arch/arm/mach-omap2/clock3517.c
+++ b/arch/arm/mach-omap2/clock3517.c
@@ -2,7 +2,7 @@
  * OMAP3517/3505-specific clock framework functions
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  *
  * Ranjith Lohithakshan
  * Paul Walmsley
@@ -119,6 +119,8 @@
 	.disable	= omap2_dflt_clk_disable,
 	.find_idlest	= am35xx_clk_ipss_find_idlest,
 	.find_companion	= omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
 };
 
 
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index e9f66b6..952c3e0 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -65,9 +65,6 @@
 	clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
 	clk_enable(dpll5_clk);
 
-	/* Enable autoidle to allow it to enter low power bypass */
-	omap3_dpll_allow_idle(dpll5_clk);
-
 	/* Program dpll5_m2_clk divider for no division */
 	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
 	clk_enable(dpll5_m2_clk);
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 052ac32..d905ecc 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP3 clock data
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * With many device clock fixes by Kevin Hilman and Jouni Högander
@@ -291,12 +291,11 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll1_ck = {
 	.name		= "dpll1_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll1_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -364,7 +363,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll2_ck = {
@@ -424,12 +422,11 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll3_ck = {
 	.name		= "dpll3_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll3_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -583,7 +580,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct dpll_data dpll4_dd_3630 __initdata = {
@@ -607,7 +603,6 @@
 	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE,
 	.flags		= DPLL_J_TYPE
 };
 
@@ -939,7 +934,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll5_ck = {
@@ -1205,7 +1199,10 @@
 	{ .parent = NULL }
 };
 
-/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */
+/*
+ * Virtual parent clock for gfx_l3_ick and gfx_l3_fck
+ * This interface clock does not have a CM_AUTOIDLE bit
+ */
 static struct clk gfx_l3_ck = {
 	.name		= "gfx_l3_ck",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1304,6 +1301,7 @@
 	.round_rate	= &omap2_clksel_round_rate
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sgx_ick = {
 	.name		= "sgx_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1328,7 +1326,7 @@
 
 static struct clk modem_fck = {
 	.name		= "modem_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
@@ -1338,7 +1336,7 @@
 
 static struct clk sad2d_ick = {
 	.name		= "sad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
@@ -1348,7 +1346,7 @@
 
 static struct clk mad2d_ick = {
 	.name		= "mad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
@@ -1718,7 +1716,7 @@
 
 static struct clk hsotgusb_ick_3430es1 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1728,7 +1726,7 @@
 
 static struct clk hsotgusb_ick_3430es2 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap3430es2_hsotgusb_wait,
+	.ops		= &clkops_omap3430es2_iclk_hsotgusb_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1736,6 +1734,7 @@
 	.recalc		= &followparent_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1767,7 +1766,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
@@ -1786,7 +1785,7 @@
 
 static struct clk usbtll_ick = {
 	.name		= "usbtll_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
@@ -1796,7 +1795,7 @@
 
 static struct clk mmchs3_ick = {
 	.name		= "mmchs3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
@@ -1807,7 +1806,7 @@
 /* Intersystem Communication Registers - chassis mode only */
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
@@ -1817,7 +1816,7 @@
 
 static struct clk aes2_ick = {
 	.name		= "aes2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
@@ -1827,7 +1826,7 @@
 
 static struct clk sha12_ick = {
 	.name		= "sha12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
@@ -1837,7 +1836,7 @@
 
 static struct clk des2_ick = {
 	.name		= "des2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
@@ -1847,7 +1846,7 @@
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
@@ -1857,7 +1856,7 @@
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
@@ -1867,7 +1866,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
@@ -1877,7 +1876,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
@@ -1887,7 +1886,7 @@
 
 static struct clk mcspi4_ick = {
 	.name		= "mcspi4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
@@ -1897,7 +1896,7 @@
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
@@ -1907,7 +1906,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
@@ -1917,7 +1916,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
@@ -1927,7 +1926,7 @@
 
 static struct clk i2c3_ick = {
 	.name		= "i2c3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
@@ -1937,7 +1936,7 @@
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
@@ -1947,7 +1946,7 @@
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
@@ -1957,7 +1956,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
@@ -1967,7 +1966,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
@@ -1977,7 +1976,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
@@ -1987,7 +1986,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
@@ -1997,7 +1996,7 @@
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
@@ -2007,7 +2006,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
@@ -2017,7 +2016,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
@@ -2027,7 +2026,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
@@ -2037,7 +2036,7 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
@@ -2057,7 +2056,7 @@
 
 static struct clk ssi_ick_3430es1 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2067,7 +2066,7 @@
 
 static struct clk ssi_ick_3430es2 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap3430es2_ssi_wait,
+	.ops		= &clkops_omap3430es2_iclk_ssi_wait,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2085,7 +2084,7 @@
 
 static struct clk usb_l4_ick = {
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -2107,7 +2106,7 @@
 
 static struct clk aes1_ick = {
 	.name		= "aes1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
@@ -2116,7 +2115,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
@@ -2125,7 +2124,7 @@
 
 static struct clk sha11_ick = {
 	.name		= "sha11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
@@ -2134,7 +2133,7 @@
 
 static struct clk des1_ick = {
 	.name		= "des1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
@@ -2195,7 +2194,7 @@
 static struct clk dss_ick_3430es1 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2206,7 +2205,7 @@
 static struct clk dss_ick_3430es2 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2229,7 +2228,7 @@
 static struct clk cam_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
@@ -2272,7 +2271,7 @@
 static struct clk usbhost_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "usbhost_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
@@ -2372,7 +2371,7 @@
 /* Never specifically named in the TRM, so we have to infer a likely name */
 static struct clk usim_ick = {
 	.name		= "usim_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
@@ -2382,7 +2381,7 @@
 
 static struct clk wdt2_ick = {
 	.name		= "wdt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
@@ -2392,7 +2391,7 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
@@ -2402,7 +2401,7 @@
 
 static struct clk gpio1_ick = {
 	.name		= "gpio1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
@@ -2412,7 +2411,7 @@
 
 static struct clk omap_32ksync_ick = {
 	.name		= "omap_32ksync_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
@@ -2423,7 +2422,7 @@
 /* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
@@ -2433,7 +2432,7 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
@@ -2663,7 +2662,7 @@
 
 static struct clk gpio6_ick = {
 	.name		= "gpio6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
@@ -2673,7 +2672,7 @@
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
@@ -2683,7 +2682,7 @@
 
 static struct clk gpio4_ick = {
 	.name		= "gpio4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
@@ -2693,7 +2692,7 @@
 
 static struct clk gpio3_ick = {
 	.name		= "gpio3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
@@ -2703,7 +2702,7 @@
 
 static struct clk gpio2_ick = {
 	.name		= "gpio2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
@@ -2713,7 +2712,7 @@
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
@@ -2723,7 +2722,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
@@ -2733,7 +2732,7 @@
 
 static struct clk uart4_ick = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
@@ -2743,7 +2742,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
@@ -2753,7 +2752,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
@@ -2763,7 +2762,7 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
@@ -2773,7 +2772,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
@@ -2783,7 +2782,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
@@ -2793,7 +2792,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
@@ -2803,7 +2802,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
@@ -2813,7 +2812,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
@@ -2823,7 +2822,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
@@ -2833,7 +2832,7 @@
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
@@ -2843,7 +2842,7 @@
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
@@ -3186,7 +3185,7 @@
  */
 static struct clk uart4_ick_am35xx = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= AM35XX_EN_UART4_SHIFT,
@@ -3538,6 +3537,9 @@
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
@@ -3551,7 +3553,8 @@
 	clk_enable_init_clocks();
 
 	/*
-	 * Lock DPLL5 and put it in autoidle.
+	 * Lock DPLL5 -- here only until other device init code can
+	 * handle this
 	 */
 	if (!cpu_is_ti816x() && (omap_rev() >= OMAP3430_REV_ES2_0))
 		omap3_clk_lock_dpll5();
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index fdbc042..f1fedb7 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -278,8 +278,10 @@
 static struct clk dpll_abe_x2_ck = {
 	.name		= "dpll_abe_x2_ck",
 	.parent		= &dpll_abe_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 };
 
 static const struct clksel_rate div31_1to31_rates[] = {
@@ -328,7 +330,7 @@
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -395,7 +397,7 @@
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -443,13 +445,14 @@
 	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_core_dd,
 	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.recalc		= &omap3_dpll_recalc,
 };
 
 static struct clk dpll_core_x2_ck = {
 	.name		= "dpll_core_x2_ck",
 	.parent		= &dpll_core_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -465,7 +468,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -495,7 +498,7 @@
 	.clksel		= dpll_core_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -515,7 +518,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -581,7 +584,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -606,7 +609,7 @@
 	.clksel		= dpll_abe_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -632,7 +635,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -689,6 +692,7 @@
 static struct clk dpll_iva_x2_ck = {
 	.name		= "dpll_iva_x2_ck",
 	.parent		= &dpll_iva_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -704,7 +708,7 @@
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -716,7 +720,7 @@
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -764,7 +768,7 @@
 	.clksel		= dpll_mpu_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_MPU,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -837,7 +841,7 @@
 	.clksel		= dpll_per_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -846,8 +850,10 @@
 static struct clk dpll_per_x2_ck = {
 	.name		= "dpll_per_x2_ck",
 	.parent		= &dpll_per_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 };
 
 static const struct clksel dpll_per_m2x2_div[] = {
@@ -861,7 +867,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -887,7 +893,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -899,7 +905,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -911,7 +917,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -923,7 +929,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -964,6 +970,7 @@
 static struct clk dpll_unipro_x2_ck = {
 	.name		= "dpll_unipro_x2_ck",
 	.parent		= &dpll_unipro_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -979,7 +986,7 @@
 	.clksel		= dpll_unipro_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -1028,7 +1035,8 @@
 static struct clk dpll_usb_clkdcoldo_ck = {
 	.name		= "dpll_usb_clkdcoldo_ck",
 	.parent		= &dpll_usb_ck,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
+	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1043,7 +1051,7 @@
 	.clksel		= dpll_usb_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_USB,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -3301,6 +3309,9 @@
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	/*
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index 1cf8131..6424d46 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -37,3 +37,9 @@
 	{ .div = 0 }
 };
 
+const struct clksel_rate dsp_ick_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 0 },
+};
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 58e42f7..ab87854 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -26,17 +26,8 @@
 
 #include <linux/bitops.h>
 
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
-#include "cminst44xx.h"
-#include "prcm44xx.h"
-
 #include <plat/clock.h>
-#include "powerdomain.h"
 #include "clockdomain.h"
-#include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
@@ -44,6 +35,7 @@
 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
 static struct clkdm_autodep *autodeps;
 
+static struct clkdm_ops *arch_clkdm;
 
 /* Private functions */
 
@@ -177,11 +169,11 @@
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_add_autodeps(struct clockdomain *clkdm)
+void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -211,11 +203,11 @@
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_del_autodeps(struct clockdomain *clkdm)
+void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -235,55 +227,29 @@
 }
 
 /**
- * _enable_hwsup - place a clockdomain into hardware-supervised idle
- * @clkdm: struct clockdomain *
+ * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
+ * @clkdm: clockdomain that we are resolving dependencies for
+ * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
  *
- * Place the clockdomain into hardware-supervised idle mode.  No return
- * value.
- *
- * XXX Should this return an error if the clockdomain does not support
- * hardware-supervised idle mode?
- */
-static void _enable_hwsup(struct clockdomain *clkdm)
-{
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-	else
-		BUG();
-}
-
-/**
- * _disable_hwsup - place a clockdomain into software-supervised idle
- * @clkdm: struct clockdomain *
- *
- * Place the clockdomain @clkdm into software-supervised idle mode.
+ * Iterates through @clkdm_deps, looking up the struct clockdomain named by
+ * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
  * No return value.
- *
- * XXX Should this return an error if the clockdomain does not support
- * software-supervised idle mode?
  */
-static void _disable_hwsup(struct clockdomain *clkdm)
+static void _resolve_clkdm_deps(struct clockdomain *clkdm,
+				struct clkdm_dep *clkdm_deps)
 {
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
-							clkdm->cm_inst,
-							clkdm->clkdm_offs);
-	else
-		BUG();
+	struct clkdm_dep *cd;
+
+	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (cd->clkdm)
+			continue;
+		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
+		     clkdm->name, cd->clkdm_name);
+	}
 }
 
 /* Public functions */
@@ -292,6 +258,7 @@
  * clkdm_init - set up the clockdomain layer
  * @clkdms: optional pointer to an array of clockdomains to register
  * @init_autodeps: optional pointer to an array of autodeps to register
+ * @custom_funcs: func pointers for arch specfic implementations
  *
  * Set up internal state.  If a pointer to an array of clockdomains
  * @clkdms was supplied, loop through the list of clockdomains,
@@ -300,12 +267,18 @@
  * @init_autodeps was provided, register those.  No return value.
  */
 void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps)
+		struct clkdm_autodep *init_autodeps,
+		struct clkdm_ops *custom_funcs)
 {
 	struct clockdomain **c = NULL;
 	struct clockdomain *clkdm;
 	struct clkdm_autodep *autodep = NULL;
 
+	if (!custom_funcs)
+		WARN(1, "No custom clkdm functions registered\n");
+	else
+		arch_clkdm = custom_funcs;
+
 	if (clkdms)
 		for (c = clkdms; *c; c++)
 			_clkdm_register(*c);
@@ -321,11 +294,14 @@
 	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2_clkdm_wakeup(clkdm);
+			clkdm_wakeup(clkdm);
 		else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
-			omap2_clkdm_deny_idle(clkdm);
+			clkdm_deny_idle(clkdm);
 
+		_resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
 		clkdm_clear_all_wkdeps(clkdm);
+
+		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
 }
@@ -422,32 +398,32 @@
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes "
 			 "up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -463,32 +439,32 @@
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
 		pr_debug("clockdomain: hardware will no longer wake up %s "
 			 "after %s wakes up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -508,26 +484,26 @@
 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
-
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic wkdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
 /**
@@ -542,33 +518,13 @@
  */
 int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s: %s: not yet implemented\n",
-		       clkdm->name, __func__);
-		return -EINVAL;
-	}
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
+		return -EINVAL;
 
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
-
-	return 0;
+	return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
 }
 
 /**
@@ -586,31 +542,33 @@
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
 		pr_debug("clockdomain: will prevent %s from sleeping if %s "
 			 "is active\n", clkdm1->name, clkdm2->name);
 
-		omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				    clkdm1->pwrdm.ptr->prcm_offs,
-				    OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -628,19 +586,23 @@
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
@@ -648,12 +610,10 @@
 			 "sleeping if %s is active\n", clkdm1->name,
 			 clkdm2->name);
 
-		omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				      clkdm1->pwrdm.ptr->prcm_offs,
-				      OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -675,25 +635,27 @@
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic sleepdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
-				       OMAP3430_CM_SLEEPDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
 /**
@@ -708,35 +670,17 @@
  */
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
+		return -EINVAL;
 
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
-			       OMAP3430_CM_SLEEPDEP);
-
-	return 0;
+	return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
 }
 
 /**
- * omap2_clkdm_sleep - force clockdomain sleep transition
+ * clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
@@ -744,7 +688,7 @@
  * clockdomain does not support software-initiated sleep; 0 upon
  * success.
  */
-int omap2_clkdm_sleep(struct clockdomain *clkdm)
+int clkdm_sleep(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -755,33 +699,16 @@
 		return -EINVAL;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
+		return -EINVAL;
+
 	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			    clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
-					      clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
-					       clkdm->cm_inst,
-					       clkdm->clkdm_offs);
-
-	} else {
-		BUG();
-	};
-
-	return 0;
+	return arch_clkdm->clkdm_sleep(clkdm);
 }
 
 /**
- * omap2_clkdm_wakeup - force clockdomain wakeup transition
+ * clkdm_wakeup - force clockdomain wakeup transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a wakeup transition on the specified
@@ -789,7 +716,7 @@
  * clockdomain does not support software-controlled wakeup; 0 upon
  * success.
  */
-int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+int clkdm_wakeup(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -800,33 +727,16 @@
 		return -EINVAL;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
+		return -EINVAL;
+
 	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			      clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
-						clkdm->cm_inst,
-						clkdm->clkdm_offs);
-
-	} else {
-		BUG();
-	};
-
-	return 0;
+	return arch_clkdm->clkdm_wakeup(clkdm);
 }
 
 /**
- * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Allow the hardware to automatically switch the clockdomain @clkdm into
@@ -835,7 +745,7 @@
  * framework, wkdep/sleepdep autodependencies are added; this is so
  * device drivers can read and write to the device.  No return value.
  */
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+void clkdm_allow_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -846,27 +756,18 @@
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
+		return;
+
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_add_autodeps(clkdm);
-	}
-
-	_enable_hwsup(clkdm);
-
+	arch_clkdm->clkdm_allow_idle(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 }
 
 /**
- * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Prevent the hardware from automatically switching the clockdomain
@@ -874,7 +775,7 @@
  * downstream clocks enabled in the clock framework, wkdep/sleepdep
  * autodependencies are removed.  No return value.
  */
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+void clkdm_deny_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -885,28 +786,20 @@
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
+		return;
+
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	_disable_hwsup(clkdm);
-
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_del_autodeps(clkdm);
-	}
+	arch_clkdm->clkdm_deny_idle(clkdm);
 }
 
 
 /* Clockdomain-to-clock framework interface code */
 
 /**
- * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
+ * clkdm_clk_enable - add an enabled downstream clock to this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the enabled downstream clock
  *
@@ -919,10 +812,8 @@
  * by on-chip processors.  Returns -EINVAL if passed null pointers;
  * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  */
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -931,6 +822,9 @@
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+		return -EINVAL;
+
 	if (atomic_inc_return(&clkdm->usecount) > 1)
 		return 0;
 
@@ -939,31 +833,7 @@
 	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_add_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_wakeup(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_wait_transition(clkdm->pwrdm.ptr);
 	pwrdm_clkdm_state_switch(clkdm);
 
@@ -971,7 +841,7 @@
 }
 
 /**
- * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
+ * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the disabled downstream clock
  *
@@ -984,10 +854,8 @@
  * is enabled; or returns 0 upon success or if the clockdomain is in
  * hwsup idle mode.
  */
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -996,6 +864,9 @@
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+		return -EINVAL;
+
 #ifdef DEBUG
 	if (atomic_read(&clkdm->usecount) == 0) {
 		WARN_ON(1); /* underflow */
@@ -1011,31 +882,7 @@
 	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_del_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_sleep(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 
 	return 0;
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 9b459c2..85b3dce 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -4,7 +4,7 @@
  * OMAP2/3 clockdomain framework functions
  *
  * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -22,11 +22,19 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
-/* Clockdomain capability flags */
+/*
+ * Clockdomain flags
+ *
+ * XXX Document CLKDM_CAN_* flags
+ *
+ * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this
+ *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.)
+ */
 #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
 #define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
 #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
+#define CLKDM_NO_AUTODEPS			(1 << 4)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
@@ -116,7 +124,42 @@
 	struct list_head node;
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
+/**
+ * struct clkdm_ops - Arch specfic function implementations
+ * @clkdm_add_wkdep: Add a wakeup dependency between clk domains
+ * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains
+ * @clkdm_read_wkdep: Read wakeup dependency state between clk domains
+ * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain
+ * @clkdm_add_sleepdep: Add a sleep dependency between clk domains
+ * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains
+ * @clkdm_read_sleepdep: Read sleep dependency state between clk domains
+ * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain
+ * @clkdm_sleep: Force a clockdomain to sleep
+ * @clkdm_wakeup: Force a clockdomain to wakeup
+ * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
+ * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
+ * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
+ * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
+ */
+struct clkdm_ops {
+	int	(*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_sleep)(struct clockdomain *clkdm);
+	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
+	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
+	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
+};
+
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
+			struct clkdm_ops *custom_funcs);
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -132,16 +175,23 @@
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
+void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle(struct clockdomain *clkdm);
 
-int omap2_clkdm_wakeup(struct clockdomain *clkdm);
-int omap2_clkdm_sleep(struct clockdomain *clkdm);
+int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep(struct clockdomain *clkdm);
 
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 
-extern void __init omap2_clockdomains_init(void);
+extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap3xxx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
+extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
+extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
+
+extern struct clkdm_ops omap2_clkdm_operations;
+extern struct clkdm_ops omap3_clkdm_operations;
+extern struct clkdm_ops omap4_clkdm_operations;
 
 #endif
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
new file mode 100644
index 0000000..48d0db7
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -0,0 +1,274 @@
+/*
+ * OMAP2 and OMAP3 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * 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/types.h>
+#include <plat/prcm.h>
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-24xx.h"
+#include "clockdomain.h"
+
+static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+						struct clockdomain *clkdm2)
+{
+	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				PM_WKDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				 PM_WKDEP);
+	return 0;
+}
+
+static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap2_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+static void _enable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+}
+
+static void _disable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+}
+
+
+static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_add_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_wakeup(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_del_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_sleep(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+struct clkdm_ops omap2_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_sleep		= omap2_clkdm_sleep,
+	.clkdm_wakeup		= omap2_clkdm_wakeup,
+	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
+
+struct clkdm_ops omap3_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
+	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
+	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
+	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
+	.clkdm_sleep		= omap3_clkdm_sleep,
+	.clkdm_wakeup		= omap3_clkdm_wakeup,
+	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
new file mode 100644
index 0000000..a1a4ecd
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -0,0 +1,137 @@
+/*
+ * OMAP4 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * 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 "clockdomain.h"
+#include "cminst44xx.h"
+#include "cm44xx.h"
+
+static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP,
+					(1 << clkdm2->dep_bit));
+}
+
+static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_wakeup(clkdm);
+
+	return 0;
+}
+
+static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_sleep(clkdm);
+
+	return 0;
+}
+
+struct clkdm_ops omap4_clkdm_operations = {
+	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_sleep		= omap4_clkdm_sleep,
+	.clkdm_wakeup		= omap4_clkdm_wakeup,
+	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index e6f0d18..13bde95 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -89,6 +89,8 @@
 
 /* 24XX-specific possible dependencies */
 
+#ifdef CONFIG_ARCH_OMAP2
+
 /* Wakeup dependency source arrays */
 
 /* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
@@ -168,6 +170,7 @@
 	{ NULL },
 };
 
+#endif /* CONFIG_ARCH_OMAP2 */
 
 /* 2430-specific possible wakeup dependencies */
 
@@ -854,7 +857,12 @@
 	NULL,
 };
 
-void __init omap2_clockdomains_init(void)
+void __init omap2xxx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap2, clkdm_autodeps);
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
+}
+
+void __init omap3xxx_clockdomains_init(void)
+{
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
 }
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index 10622c9..a607ec1 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -18,11 +18,6 @@
  * published by the Free Software Foundation.
  */
 
-/*
- * To-Do List
- * -> Populate the Sleep/Wakeup dependencies for the domains
- */
-
 #include <linux/kernel.h>
 #include <linux/io.h>
 
@@ -35,6 +30,355 @@
 #include "prcm44xx.h"
 #include "prcm_mpu44xx.h"
 
+/* Static Dependencies for OMAP4 Clock Domains */
+
+static struct clkdm_dep ducati_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep iss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep mpuss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep tesla_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
 
 static struct clockdomain l4_cefuse_44xx_clkdm = {
 	.name		  = "l4_cefuse_clkdm",
@@ -52,6 +396,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
+	.dep_bit	  = OMAP4430_L4CFG_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -62,6 +407,9 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_TESLA_INST,
 	.clkdm_offs	  = OMAP4430_CM1_TESLA_TESLA_CDOFFS,
+	.dep_bit	  = OMAP4430_TESLA_STATDEP_SHIFT,
+	.wkdep_srcs	  = tesla_wkup_sleep_deps,
+	.sleepdep_srcs	  = tesla_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -72,6 +420,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_GFX_INST,
 	.clkdm_offs	  = OMAP4430_CM2_GFX_GFX_CDOFFS,
+	.dep_bit	  = OMAP4430_GFX_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_gfx_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -82,6 +433,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_IVAHD_INST,
 	.clkdm_offs	  = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS,
+	.dep_bit	  = OMAP4430_IVAHD_STATDEP_SHIFT,
+	.wkdep_srcs	  = ivahd_wkup_sleep_deps,
+	.sleepdep_srcs	  = ivahd_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -92,6 +446,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4SEC_CDOFFS,
+	.dep_bit	  = OMAP4430_L4SEC_STATDEP_SHIFT,
+	.wkdep_srcs	  = l4_secure_wkup_sleep_deps,
+	.sleepdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -102,6 +459,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
+	.dep_bit	  = OMAP4430_L4PER_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -112,6 +470,7 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_ABE_INST,
 	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
+	.dep_bit	  = OMAP4430_ABE_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -131,6 +490,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L3INIT_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS,
+	.dep_bit	  = OMAP4430_L3INIT_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -141,6 +503,8 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_MPU_INST,
 	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
+	.wkdep_srcs	  = mpuss_wkup_sleep_deps,
+	.sleepdep_srcs	  = mpuss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -150,7 +514,7 @@
 	.pwrdm		  = { .name = "cpu0_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -160,7 +524,7 @@
 	.pwrdm		  = { .name = "cpu1_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -171,6 +535,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
+	.dep_bit	  = OMAP4430_MEMIF_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -191,6 +556,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_DUCATI_CDOFFS,
+	.dep_bit	  = OMAP4430_DUCATI_STATDEP_SHIFT,
+	.wkdep_srcs	  = ducati_wkup_sleep_deps,
+	.sleepdep_srcs	  = ducati_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -201,6 +569,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_2_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -211,6 +580,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_1_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -221,6 +591,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
+	.wkdep_srcs	  = l3_d2d_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -231,6 +603,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CAM_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CAM_CAM_CDOFFS,
+	.wkdep_srcs	  = iss_wkup_sleep_deps,
+	.sleepdep_srcs	  = iss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -241,6 +615,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_DSS_INST,
 	.clkdm_offs	  = OMAP4430_CM2_DSS_DSS_CDOFFS,
+	.dep_bit	  = OMAP4430_DSS_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_dss_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -251,6 +628,7 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.cm_inst	  = OMAP4430_PRM_WKUP_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
+	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -271,6 +649,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_SDMA_CDOFFS,
+	.wkdep_srcs	  = l3_dma_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -305,5 +685,5 @@
 
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL);
+	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
 }
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index d70660e..6862904 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -210,8 +210,11 @@
 #define OMAP24XX_AUTO_USB_MASK				(1 << 0)
 
 /* CM_AUTOIDLE3_CORE */
+#define OMAP24XX_AUTO_SDRC_SHIFT			2
 #define OMAP24XX_AUTO_SDRC_MASK				(1 << 2)
+#define OMAP24XX_AUTO_GPMC_SHIFT			1
 #define OMAP24XX_AUTO_GPMC_MASK				(1 << 1)
+#define OMAP24XX_AUTO_SDMA_SHIFT			0
 #define OMAP24XX_AUTO_SDMA_MASK				(1 << 0)
 
 /* CM_AUTOIDLE4_CORE */
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
index 96954aa..9d0dec8 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -25,6 +25,14 @@
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
+#define DPLL_AUTOIDLE_DISABLE				0x0
+#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
+#define OMAP2XXX_APLL_AUTOIDLE_DISABLE			0x0
+#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
 static const u8 cm_idlest_offs[] = {
 	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
 };
@@ -125,6 +133,67 @@
 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
 }
 
+/*
+ * DPLL autoidle control
+ */
+
+static void _omap2xxx_set_dpll_autoidle(u8 m)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~OMAP24XX_AUTO_DPLL_MASK;
+	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_dpll_disable_autoidle(void)
+{
+	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
+}
+
+void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
+{
+	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
+}
+
+/*
+ * APLL autoidle control
+ */
+
+static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~mask;
+	v |= m << __ffs(mask);
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_apll54_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_96M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_96M_MASK);
+}
 
 /*
  *
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h
index 5e9ea5b..088bbad 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h
@@ -122,6 +122,14 @@
 extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
 extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
 
+extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
+extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
+
+extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
+extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+
 #endif
 
 /* CM register bits shared between 24XX and 3430 */
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 48fc3f4..0b87ec8 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -21,6 +21,7 @@
 #include "cm.h"
 
 #define OMAP4_CM_CLKSTCTRL				0x0000
+#define OMAP4_CM_STATICDEP				0x0004
 
 /* Function prototypes */
 # ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index c04bbbe..a482bfa 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -73,6 +73,27 @@
 	return v;
 }
 
+u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
+}
+
+u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
+}
+
+u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
 /*
  *
  */
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index a6abd0a..2b32c18 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -25,6 +25,12 @@
 extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
 extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
 					   s16 inst, s16 idx);
+extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
+					   u32 mask);
 
 extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
 
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index f7b22a1..7cc8071 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -99,14 +99,14 @@
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_allow_idle(clkdm);
+	clkdm_allow_idle(clkdm);
 	return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_deny_idle(clkdm);
+	clkdm_deny_idle(clkdm);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 2cb720b..0d2d6a9 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -36,6 +36,70 @@
 #include "mux.h"
 #include "control.h"
 
+#define L3_MODULES_MAX_LEN 12
+#define L3_MODULES 3
+
+static int __init omap3_l3_init(void)
+{
+	int l;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap34xx()))
+		return -ENODEV;
+
+	l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
+
+	oh = omap_hwmod_lookup(oh_name);
+
+	if (!oh)
+		pr_err("could not look up %s\n", oh_name);
+
+	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+							   NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return PTR_ERR(od);
+}
+postcore_initcall(omap3_l3_init);
+
+static int __init omap4_l3_init(void)
+{
+	int l, i;
+	struct omap_hwmod *oh[3];
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap44xx()))
+		return -ENODEV;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
+
+		oh[i] = omap_hwmod_lookup(oh_name);
+		if (!(oh[i]))
+			pr_err("could not look up %s\n", oh_name);
+	}
+
+	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+						     0, NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return PTR_ERR(od);
+}
+postcore_initcall(omap4_l3_init);
+
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
 static struct resource cam_resources[] = {
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
new file mode 100644
index 0000000..4e4da61
--- /dev/null
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -0,0 +1,84 @@
+/*
+ * OMAP4-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak
+ *
+ * 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/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm-regbits-44xx.h"
+
+/* Supported only on OMAP4 */
+int omap4_dpllmx_gatectrl_read(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return -EINVAL;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Clear the bit to allow gatectrl */
+	v &= ~mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Set the bit to deny gatectrl */
+	v |= mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+const struct clkops clkops_omap4_dpllmx_ops = {
+	.allow_idle	= omap4_dpllmx_allow_gatectrl,
+	.deny_idle	= omap4_dpllmx_deny_gatectrl,
+};
+
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 657f3c8..441e79d 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -356,15 +356,15 @@
 
 	if (cpu_is_omap242x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2420_hwmod_init();
 	} else if (cpu_is_omap243x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2430_hwmod_init();
 	} else if (cpu_is_omap34xx()) {
 		omap3xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap3xxx_clockdomains_init();
 		omap3xxx_hwmod_init();
 	} else if (cpu_is_omap44xx()) {
 		omap44xx_powerdomains_init();
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 1125134..e39772b 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -457,14 +457,18 @@
  * will be accessed by a particular initiator (e.g., if a module will
  * be accessed by the IVA, there should be a sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_add_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Otherwise, returns -EINVAL upon error or
+ * passes along clkdm_add_sleepdep() value upon success.
  */
 static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -477,14 +481,18 @@
  * be accessed by a particular initiator (e.g., if a module will not
  * be accessed by the IVA, there should be no sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_del_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Returns -EINVAL upon error or passes
+ * along clkdm_del_sleepdep() value upon success.
  */
 static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -1283,6 +1291,42 @@
 }
 
 /**
+ * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
+ * @oh: struct omap_hwmod *
+ * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
+ *
+ * Sets the IP block's OCP autoidle bit in hardware, and updates our
+ * local copy. Intended to be used by drivers that require
+ * direct manipulation of the AUTOIDLE bits.
+ * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
+ * along the return value from _set_module_autoidle().
+ *
+ * Any users of this function should be scrutinized carefully.
+ */
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
+{
+	u32 v;
+	int retval = 0;
+	unsigned long flags;
+
+	if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
+		return -EINVAL;
+
+	spin_lock_irqsave(&oh->_lock, flags);
+
+	v = oh->_sysc_cache;
+
+	retval = _set_module_autoidle(oh, autoidle, &v);
+
+	if (!retval)
+		_write_sysconfig(v, oh);
+
+	spin_unlock_irqrestore(&oh->_lock, flags);
+
+	return retval;
+}
+
+/**
  * _shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -2286,3 +2330,29 @@
 
 	return ret;
 }
+
+/**
+ * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup
+ * @oh: struct omap_hwmod *
+ *
+ * Prevent the hwmod @oh from being reset during the setup process.
+ * Intended for use by board-*.c files on boards with devices that
+ * cannot tolerate being reset.  Must be called before the hwmod has
+ * been set up.  Returns 0 upon success or negative error code upon
+ * failure.
+ */
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
+{
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->_state != _HWMOD_STATE_REGISTERED) {
+		pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n",
+			oh->name);
+		return -EINVAL;
+	}
+
+	oh->flags |= HWMOD_INIT_NO_RESET;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index e0bc2c7..61e58bd 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1410,6 +1410,7 @@
 			.flags	= OMAP_FIREWALL_L4,
 		}
 	},
+	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 4aa74d7..490789a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1485,6 +1485,7 @@
 	.clk		= "dss_54m_fck",
 	.addr		= omap2430_dss_venc_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap2430_dss_venc_addrs),
+	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index e2792cf..2e275cb 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -100,10 +100,26 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L3 taret configuration and error log registers */
+static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
+	{ .irq = INT_34XX_L3_DBG_IRQ },
+	{ .irq = INT_34XX_L3_APP_IRQ },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
+	{
+		.pa_start       = 0x68000000,
+		.pa_end         = 0x6800ffff,
+		.flags          = ADDR_TYPE_RT,
+	},
+};
+
 /* MPU -> L3 interface */
 static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
-	.master = &omap3xxx_mpu_hwmod,
-	.slave	= &omap3xxx_l3_main_hwmod,
+	.master   = &omap3xxx_mpu_hwmod,
+	.slave    = &omap3xxx_l3_main_hwmod,
+	.addr     = omap3xxx_l3_main_addrs,
+	.addr_cnt = ARRAY_SIZE(omap3xxx_l3_main_addrs),
 	.user	= OCP_USER_MPU,
 };
 
@@ -135,6 +151,8 @@
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
 	.class		= &l3_hwmod_class,
+	.mpu_irqs       = omap3xxx_l3_main_irqs,
+	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
 	.masters	= omap3xxx_l3_main_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
@@ -473,26 +491,12 @@
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
-	&omap3_l4_core__sr1,
-	&omap3_l4_core__sr2,
-};
-
-/* Master interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
-	&omap3xxx_l4_core__l4_wkup,
-	&omap3_l4_core__uart1,
-	&omap3_l4_core__uart2,
-	&omap3_l4_core__i2c1,
-	&omap3_l4_core__i2c2,
-	&omap3_l4_core__i2c3,
 };
 
 /* L4 CORE */
 static struct omap_hwmod omap3xxx_l4_core_hwmod = {
 	.name		= "l4_core",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_core_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_core_masters),
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -504,18 +508,10 @@
 	&omap3xxx_l3_main__l4_per,
 };
 
-/* Master interfaces on the L4_PER interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
-	&omap3_l4_per__uart3,
-	&omap3_l4_per__uart4,
-};
-
 /* L4 PER */
 static struct omap_hwmod omap3xxx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_per_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_per_masters),
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -527,16 +523,10 @@
 	&omap3xxx_l4_core__l4_wkup,
 };
 
-/* Master interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_masters[] = {
-};
-
 /* L4 WKUP */
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_wkup_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_masters),
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -1294,6 +1284,11 @@
 	.slaves		= omap3xxx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	/*
+	 * XXX: Use software supervised mode, HW supervised smartidle seems to
+	 * block CORE power domain idle transitions. Maybe a HW bug in wdt2?
+	 */
+	.flags		= HWMOD_SWSUP_SIDLE,
 };
 
 /* UART common */
@@ -1844,6 +1839,7 @@
 			.flags	= OMAP_FIREWALL_L4,
 		}
 	},
+	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 7b72316..3e88dd3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -264,11 +264,27 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L3 target configuration and error log registers */
+static struct omap_hwmod_irq_info omap44xx_l3_targ_irqs[] = {
+	{ .irq = 9  + OMAP44XX_IRQ_GIC_START },
+	{ .irq = 10 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
+	{
+		.pa_start	= 0x44000000,
+		.pa_end		= 0x44000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* mpu -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
 	.master		= &omap44xx_mpu_hwmod,
 	.slave		= &omap44xx_l3_main_1_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -286,6 +302,8 @@
 static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
+	.mpu_irqs	= omap44xx_l3_targ_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_l3_targ_irqs),
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -332,11 +350,21 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
+	{
+		.pa_start	= 0x44800000,
+		.pa_end		= 0x44801fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -377,11 +405,21 @@
 };
 
 /* l3_main_3 interface data */
+static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
+	{
+		.pa_start	= 0x45000000,
+		.pa_end		= 0x45000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_3 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_3_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
new file mode 100644
index 0000000..82632c2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -0,0 +1,253 @@
+/*
+  * OMAP4XXX L3 Interconnect error handling driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "omap_l3_noc.h"
+
+/*
+ * Interrupt Handler for L3 error detection.
+ *	1) Identify the L3 clockdomain partition to which the error belongs to.
+ *	2) Identify the slave where the error information is logged
+ *	3) Print the logged information.
+ *	4) Add dump stack to provide kernel trace.
+ *
+ * Two Types of errors :
+ *	1) Custom errors in L3 :
+ *		Target like DMM/FW/EMIF generates SRESP=ERR error
+ *	2) Standard L3 error:
+ *		- Unsupported CMD.
+ *			L3 tries to access target while it is idle
+ *		- OCP disconnect.
+ *		- Address hole error:
+ *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
+ *			do not have connectivity, the error is logged in
+ *			their default target which is DMM2.
+ *
+ *	On High Secure devices, firewall errors are possible and those
+ *	can be trapped as well. But the trapping is implemented as part
+ *	secure software and hence need not be implemented here.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+
+	struct omap4_l3		*l3 = _l3;
+	int inttype, i, j;
+	int err_src = 0;
+	u32 std_err_main_addr, std_err_main, err_reg;
+	u32 base, slave_addr, clear;
+	char *source_name;
+
+	/* Get the Type of interrupt */
+	if (irq == l3->app_irq)
+		inttype = L3_APPLICATION_ERROR;
+	else
+		inttype = L3_DEBUG_ERROR;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		/*
+		 * Read the regerr register of the clock domain
+		 * to determine the source
+		 */
+		base = (u32)l3->l3_base[i];
+		err_reg =  readl(base + l3_flagmux[i] + (inttype << 3));
+
+		/* Get the corresponding error and analyse */
+		if (err_reg) {
+			/* Identify the source from control status register */
+			for (j = 0; !(err_reg & (1 << j)); j++)
+									;
+
+			err_src = j;
+			/* Read the stderrlog_main_source from clk domain */
+			std_err_main_addr = base + (*(l3_targ[i] + err_src));
+			std_err_main =  readl(std_err_main_addr);
+
+			switch ((std_err_main & CUSTOM_ERROR)) {
+			case STANDARD_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				slave_addr = std_err_main_addr +
+						L3_SLAVE_ADDRESS_OFFSET;
+				WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
+					source_name, readl(slave_addr));
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			case CUSTOM_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
+							source_name);
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			default:
+				/* Nothing to be handled here as of now */
+				break;
+			}
+		/* Error found so break the for loop */
+		break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init omap4_l3_probe(struct platform_device *pdev)
+{
+	static struct omap4_l3		*l3;
+	struct resource		*res;
+	int			ret;
+	int			irq;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3)
+		ret = -ENOMEM;
+
+	platform_set_drvdata(pdev, l3);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 0\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	l3->l3_base[0] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[0])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 1\n");
+		ret = -ENODEV;
+		goto err3;
+	}
+
+	l3->l3_base[1] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[1])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 2\n");
+		ret = -ENODEV;
+		goto err5;
+	}
+
+	l3->l3_base[2] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[2])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err6;
+	}
+
+	/*
+	 * Setup interrupt Handlers
+	 */
+	irq = platform_get_irq(pdev, 0);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-dbg-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_DBG);
+		goto err7;
+	}
+	l3->debug_irq = irq;
+
+	irq = platform_get_irq(pdev, 1);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-app-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_APP);
+		goto err8;
+	}
+	l3->app_irq = irq;
+
+	goto err0;
+err8:
+err7:
+	iounmap(l3->l3_base[2]);
+err6:
+err5:
+	iounmap(l3->l3_base[1]);
+err4:
+err3:
+	iounmap(l3->l3_base[0]);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap4_l3_remove(struct platform_device *pdev)
+{
+	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->l3_base[0]);
+	iounmap(l3->l3_base[1]);
+	iounmap(l3->l3_base[2]);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap4_l3_driver = {
+	.remove		= __exit_p(omap4_l3_remove),
+	.driver		= {
+	.name		= "omap_l3_noc",
+	},
+};
+
+static int __init omap4_l3_init(void)
+{
+	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+}
+postcore_initcall_sync(omap4_l3_init);
+
+static void __exit omap4_l3_exit(void)
+{
+	platform_driver_unregister(&omap4_l3_driver);
+}
+module_exit(omap4_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
new file mode 100644
index 0000000..359b833
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_noc.h
@@ -0,0 +1,132 @@
+ /*
+  * OMAP4XXX L3 Interconnect  error handling driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/*
+ * L3 register offsets
+ */
+#define L3_MODULES			3
+#define CLEAR_STDERR_LOG		(1 << 31)
+#define CUSTOM_ERROR			0x2
+#define STANDARD_ERROR			0x0
+#define INBAND_ERROR			0x0
+#define EMIF_KERRLOG_OFFSET		0x10
+#define L3_SLAVE_ADDRESS_OFFSET		0x14
+#define LOGICAL_ADDR_ERRORLOG		0x4
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+u32 l3_flagmux[L3_MODULES] = {
+	0x50C,
+	0x100C,
+	0X020C
+};
+
+/*
+ * L3 Target standard Error register offsets
+ */
+u32 l3_targ_stderrlog_main_clk1[] = {
+	0x148, /* DMM1 */
+	0x248, /* DMM2 */
+	0x348, /* ABE */
+	0x448, /* L4CFG */
+	0x648  /* CLK2 PWR DISC */
+};
+
+u32 l3_targ_stderrlog_main_clk2[] = {
+	0x548,		/* CORTEX M3 */
+	0x348,		/* DSS */
+	0x148,		/* GPMC */
+	0x448,		/* ISS */
+	0x748,		/* IVAHD */
+	0xD48,		/* missing in TRM  corresponds to AES1*/
+	0x948,		/* L4 PER0*/
+	0x248,		/* OCMRAM */
+	0x148,		/* missing in TRM corresponds to GPMC sERROR*/
+	0x648,		/* SGX */
+	0x848,		/* SL2 */
+	0x1648,		/* C2C */
+	0x1148,		/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF48,		/* missing in TRM corrsponds to SHA1*/
+	0xE48,		/* missing in TRM corresponds to AES2*/
+	0xC48,		/* L4 PER3 */
+	0xA48,		/* L4 PER1*/
+	0xB48		/* L4 PER2*/
+};
+
+u32 l3_targ_stderrlog_main_clk3[] = {
+	0x0148	/* EMUSS */
+};
+
+char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+	{
+	"DMM1",
+	"DMM2",
+	"ABE",
+	"L4CFG",
+	"CLK2 PWR DISC",
+	},
+	{
+	"CORTEX M3" ,
+	"DSS ",
+	"GPMC ",
+	"ISS ",
+	"IVAHD ",
+	"AES1",
+	"L4 PER0",
+	"OCMRAM ",
+	"GPMC sERROR",
+	"SGX ",
+	"SL2 ",
+	"C2C ",
+	"PWR DISC CLK1",
+	"SHA1",
+	"AES2",
+	"L4 PER3",
+	"L4 PER1",
+	"L4 PER2",
+	},
+	{
+	"EMUSS",
+	},
+};
+
+u32 *l3_targ[L3_MODULES] = {
+	l3_targ_stderrlog_main_clk1,
+	l3_targ_stderrlog_main_clk2,
+	l3_targ_stderrlog_main_clk3,
+};
+
+struct omap4_l3 {
+	struct device	*dev;
+	struct clk	*ick;
+
+	/* memory base */
+	void __iomem *l3_base[4];
+
+	int		debug_irq;
+	int		app_irq;
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c
new file mode 100644
index 0000000..265bff3
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_smx.c
@@ -0,0 +1,314 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include "omap_l3_smx.h"
+
+static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
+{
+	return __raw_readll(base + reg);
+}
+
+static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
+{
+	__raw_writell(value, base + reg);
+}
+
+static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
+{
+	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
+}
+
+static inline u32 omap3_l3_decode_addr(u64 error_addr)
+{
+	return error_addr & 0xffffffff;
+}
+
+static inline unsigned omap3_l3_decode_cmd(u64 error)
+{
+	return (error & 0x07) >> L3_ERROR_LOG_CMD;
+}
+
+static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
+{
+	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
+}
+
+static inline unsigned omap3_l3_decode_req_info(u64 error)
+{
+	return (error >> 32) & 0xffff;
+}
+
+static char *omap3_l3_code_string(u8 code)
+{
+	switch (code) {
+	case OMAP_L3_CODE_NOERROR:
+		return "No Error";
+	case OMAP_L3_CODE_UNSUP_CMD:
+		return "Unsupported Command";
+	case OMAP_L3_CODE_ADDR_HOLE:
+		return "Address Hole";
+	case OMAP_L3_CODE_PROTECT_VIOLATION:
+		return "Protection Violation";
+	case OMAP_L3_CODE_IN_BAND_ERR:
+		return "In-band Error";
+	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
+		return "Request Timeout Not Accepted";
+	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
+		return "Request Timeout, no response";
+	default:
+		return "UNKNOWN error";
+	}
+}
+
+static char *omap3_l3_initiator_string(u8 initid)
+{
+	switch (initid) {
+	case OMAP_L3_LCD:
+		return "LCD";
+	case OMAP_L3_SAD2D:
+		return "SAD2D";
+	case OMAP_L3_IA_MPU_SS_1:
+	case OMAP_L3_IA_MPU_SS_2:
+	case OMAP_L3_IA_MPU_SS_3:
+	case OMAP_L3_IA_MPU_SS_4:
+	case OMAP_L3_IA_MPU_SS_5:
+		return "MPU";
+	case OMAP_L3_IA_IVA_SS_1:
+	case OMAP_L3_IA_IVA_SS_2:
+	case OMAP_L3_IA_IVA_SS_3:
+		return "IVA_SS";
+	case OMAP_L3_IA_IVA_SS_DMA_1:
+	case OMAP_L3_IA_IVA_SS_DMA_2:
+	case OMAP_L3_IA_IVA_SS_DMA_3:
+	case OMAP_L3_IA_IVA_SS_DMA_4:
+	case OMAP_L3_IA_IVA_SS_DMA_5:
+	case OMAP_L3_IA_IVA_SS_DMA_6:
+		return "IVA_SS_DMA";
+	case OMAP_L3_IA_SGX:
+		return "SGX";
+	case OMAP_L3_IA_CAM_1:
+	case OMAP_L3_IA_CAM_2:
+	case OMAP_L3_IA_CAM_3:
+		return "CAM";
+	case OMAP_L3_IA_DAP:
+		return "DAP";
+	case OMAP_L3_SDMA_WR_1:
+	case OMAP_L3_SDMA_WR_2:
+		return "SDMA_WR";
+	case OMAP_L3_SDMA_RD_1:
+	case OMAP_L3_SDMA_RD_2:
+	case OMAP_L3_SDMA_RD_3:
+	case OMAP_L3_SDMA_RD_4:
+		return "SDMA_RD";
+	case OMAP_L3_USBOTG:
+		return "USB_OTG";
+	case OMAP_L3_USBHOST:
+		return "USB_HOST";
+	default:
+		return "UNKNOWN Initiator";
+	}
+}
+
+/**
+ * omap3_l3_block_irq - handles a register block's irq
+ * @l3: struct omap3_l3 *
+ * @base: register block base address
+ * @error: L3_ERROR_LOG register of our block
+ *
+ * Called in hard-irq context. Caller should take care of locking
+ *
+ * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
+ * Analysis Sequence, we are following that sequence here, please
+ * refer to that Figure for more information on the subject.
+ */
+static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
+					u64 error, int error_addr)
+{
+	u8                      code = omap3_l3_decode_error_code(error);
+	u8                      initid = omap3_l3_decode_initid(error);
+	u8                      multi = error & L3_ERROR_LOG_MULTI;
+	u32			address = omap3_l3_decode_addr(error_addr);
+
+	WARN(true, "%s Error seen by %s %s at address %x\n",
+				 omap3_l3_code_string(code),
+			  omap3_l3_initiator_string(initid),
+			     multi ? "Multiple Errors" : "",
+						   address);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
+{
+	struct omap3_l3         *l3 = _l3;
+
+	u64                     status, clear;
+	u64                     error;
+	u64			error_addr;
+	u64			err_source = 0;
+	void			__iomem *base;
+	int			int_type;
+
+	irqreturn_t             ret = IRQ_NONE;
+
+	if (irq == l3->app_irq)
+		int_type = L3_APPLICATION_ERROR;
+	else
+		int_type = L3_DEBUG_ERROR;
+
+	if (!int_type) {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
+		/*
+		 * if we have a timeout error, there's nothing we can
+		 * do besides rebooting the board. So let's BUG on any
+		 * of such errors and handle the others. timeout error
+		 * is severe and not expected to occur.
+		 */
+		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
+	} else {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
+		/* No timeout error for debug sources */
+	}
+
+	base = ((l3->rt) + (*(omap3_l3_bases[int_type] + err_source)));
+
+	/* identify the error source */
+	for (err_source = 0; !(status & (1 << err_source)); err_source++)
+									;
+	error = omap3_l3_readll(base, L3_ERROR_LOG);
+
+	if (error) {
+		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
+
+		ret |= omap3_l3_block_irq(l3, error, error_addr);
+	}
+
+	/* Clear the status register */
+	clear = ((L3_AGENT_STATUS_CLEAR_IA << int_type) |
+		 (L3_AGENT_STATUS_CLEAR_TA));
+
+	omap3_l3_writell(base, L3_AGENT_STATUS, clear);
+
+	/* clear the error log register */
+	omap3_l3_writell(base, L3_ERROR_LOG, error);
+
+	return ret;
+}
+
+static int __init omap3_l3_probe(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3;
+	struct resource         *res;
+	int                     ret;
+	int                     irq;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, l3);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+	l3->rt = ioremap(res->start, resource_size(res));
+	if (!(l3->rt)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = request_irq(irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-debug-irq", l3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request debug irq\n");
+		goto err3;
+	}
+	l3->debug_irq = irq;
+
+	irq = platform_get_irq(pdev, 1);
+	ret = request_irq(irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-app-irq", l3);
+
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request app irq\n");
+		goto err4;
+	}
+
+	l3->app_irq = irq;
+	goto err0;
+
+err4:
+err3:
+	iounmap(l3->rt);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap3_l3_remove(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->rt);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap3_l3_driver = {
+	.remove         = __exit_p(omap3_l3_remove),
+	.driver         = {
+	.name   = "omap_l3_smx",
+	},
+};
+
+static int __init omap3_l3_init(void)
+{
+	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
+}
+postcore_initcall_sync(omap3_l3_init);
+
+static void __exit omap3_l3_exit(void)
+{
+	platform_driver_unregister(&omap3_l3_driver);
+}
+module_exit(omap3_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_smx.h b/arch/arm/mach-omap2/omap_l3_smx.h
new file mode 100644
index 0000000..ba2ed9a
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_smx.h
@@ -0,0 +1,338 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/* Register definitions. All 64-bit wide */
+#define L3_COMPONENT			0x000
+#define L3_CORE				0x018
+#define L3_AGENT_CONTROL		0x020
+#define L3_AGENT_STATUS			0x028
+#define L3_ERROR_LOG			0x058
+
+#define L3_ERROR_LOG_MULTI		(1 << 31)
+#define L3_ERROR_LOG_SECONDARY		(1 << 30)
+
+#define L3_ERROR_LOG_ADDR		0x060
+
+/* Register definitions for Sideband Interconnect */
+#define L3_SI_CONTROL			0x020
+#define L3_SI_FLAG_STATUS_0		0x510
+
+const u64 shift = 1;
+
+#define L3_STATUS_0_MPUIA_BRST		(shift << 0)
+#define L3_STATUS_0_MPUIA_RSP		(shift << 1)
+#define L3_STATUS_0_MPUIA_INBAND	(shift << 2)
+#define L3_STATUS_0_IVAIA_BRST		(shift << 6)
+#define L3_STATUS_0_IVAIA_RSP		(shift << 7)
+#define L3_STATUS_0_IVAIA_INBAND	(shift << 8)
+#define L3_STATUS_0_SGXIA_BRST		(shift << 9)
+#define L3_STATUS_0_SGXIA_RSP		(shift << 10)
+#define L3_STATUS_0_SGXIA_MERROR	(shift << 11)
+#define L3_STATUS_0_CAMIA_BRST		(shift << 12)
+#define L3_STATUS_0_CAMIA_RSP		(shift << 13)
+#define L3_STATUS_0_CAMIA_INBAND	(shift << 14)
+#define L3_STATUS_0_DISPIA_BRST		(shift << 15)
+#define L3_STATUS_0_DISPIA_RSP		(shift << 16)
+#define L3_STATUS_0_DMARDIA_BRST	(shift << 18)
+#define L3_STATUS_0_DMARDIA_RSP		(shift << 19)
+#define L3_STATUS_0_DMAWRIA_BRST	(shift << 21)
+#define L3_STATUS_0_DMAWRIA_RSP		(shift << 22)
+#define L3_STATUS_0_USBOTGIA_BRST	(shift << 24)
+#define L3_STATUS_0_USBOTGIA_RSP	(shift << 25)
+#define L3_STATUS_0_USBOTGIA_INBAND	(shift << 26)
+#define L3_STATUS_0_USBHOSTIA_BRST	(shift << 27)
+#define L3_STATUS_0_USBHOSTIA_INBAND	(shift << 28)
+#define L3_STATUS_0_SMSTA_REQ		(shift << 48)
+#define L3_STATUS_0_GPMCTA_REQ		(shift << 49)
+#define L3_STATUS_0_OCMRAMTA_REQ	(shift << 50)
+#define L3_STATUS_0_OCMROMTA_REQ	(shift << 51)
+#define L3_STATUS_0_IVATA_REQ		(shift << 54)
+#define L3_STATUS_0_SGXTA_REQ		(shift << 55)
+#define L3_STATUS_0_SGXTA_SERROR	(shift << 56)
+#define L3_STATUS_0_GPMCTA_SERROR	(shift << 57)
+#define L3_STATUS_0_L4CORETA_REQ	(shift << 58)
+#define L3_STATUS_0_L4PERTA_REQ		(shift << 59)
+#define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
+#define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
+
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST         \
+					| L3_STATUS_0_MPUIA_RSP         \
+					| L3_STATUS_0_IVAIA_BRST        \
+					| L3_STATUS_0_IVAIA_RSP         \
+					| L3_STATUS_0_SGXIA_BRST        \
+					| L3_STATUS_0_SGXIA_RSP         \
+					| L3_STATUS_0_CAMIA_BRST        \
+					| L3_STATUS_0_CAMIA_RSP         \
+					| L3_STATUS_0_DISPIA_BRST       \
+					| L3_STATUS_0_DISPIA_RSP        \
+					| L3_STATUS_0_DMARDIA_BRST      \
+					| L3_STATUS_0_DMARDIA_RSP       \
+					| L3_STATUS_0_DMAWRIA_BRST      \
+					| L3_STATUS_0_DMAWRIA_RSP       \
+					| L3_STATUS_0_USBOTGIA_BRST     \
+					| L3_STATUS_0_USBOTGIA_RSP      \
+					| L3_STATUS_0_USBHOSTIA_BRST    \
+					| L3_STATUS_0_SMSTA_REQ         \
+					| L3_STATUS_0_GPMCTA_REQ        \
+					| L3_STATUS_0_OCMRAMTA_REQ      \
+					| L3_STATUS_0_OCMROMTA_REQ      \
+					| L3_STATUS_0_IVATA_REQ         \
+					| L3_STATUS_0_SGXTA_REQ         \
+					| L3_STATUS_0_L4CORETA_REQ      \
+					| L3_STATUS_0_L4PERTA_REQ       \
+					| L3_STATUS_0_L4EMUTA_REQ       \
+					| L3_STATUS_0_MAD2DTA_REQ)
+
+#define L3_SI_FLAG_STATUS_1		0x530
+
+#define L3_STATUS_1_MPU_DATAIA		(1 << 0)
+#define L3_STATUS_1_DAPIA0		(1 << 3)
+#define L3_STATUS_1_DAPIA1		(1 << 4)
+#define L3_STATUS_1_IVAIA		(1 << 6)
+
+#define L3_PM_ERROR_LOG			0x020
+#define L3_PM_CONTROL			0x028
+#define L3_PM_ERROR_CLEAR_SINGLE	0x030
+#define L3_PM_ERROR_CLEAR_MULTI		0x038
+#define L3_PM_REQ_INFO_PERMISSION(n)	(0x048 + (0x020 * n))
+#define L3_PM_READ_PERMISSION(n)	(0x050 + (0x020 * n))
+#define L3_PM_WRITE_PERMISSION(n)	(0x058 + (0x020 * n))
+#define L3_PM_ADDR_MATCH(n)		(0x060 + (0x020 * n))
+
+/* L3 error log bit fields. Common for IA and TA */
+#define L3_ERROR_LOG_CODE		24
+#define L3_ERROR_LOG_INITID		8
+#define L3_ERROR_LOG_CMD		0
+
+/* L3 agent status bit fields. */
+#define L3_AGENT_STATUS_CLEAR_IA	0x10000000
+#define L3_AGENT_STATUS_CLEAR_TA	0x01000000
+
+#define OMAP34xx_IRQ_L3_APP		10
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+enum omap3_l3_initiator_id {
+	/* LCD has 1 ID */
+	OMAP_L3_LCD	        = 29,
+	/* SAD2D has 1 ID */
+	OMAP_L3_SAD2D		= 28,
+	/* MPU has 5 IDs */
+	OMAP_L3_IA_MPU_SS_1     = 27,
+	OMAP_L3_IA_MPU_SS_2     = 26,
+	OMAP_L3_IA_MPU_SS_3     = 25,
+	OMAP_L3_IA_MPU_SS_4     = 24,
+	OMAP_L3_IA_MPU_SS_5     = 23,
+	/* IVA2.2 SS has 3 IDs*/
+	OMAP_L3_IA_IVA_SS_1     = 22,
+	OMAP_L3_IA_IVA_SS_2     = 21,
+	OMAP_L3_IA_IVA_SS_3     = 20,
+	/* IVA 2.2 SS DMA has 6 IDS */
+	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
+	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
+	OMAP_L3_IA_IVA_SS_DMA_3 = 17,
+	OMAP_L3_IA_IVA_SS_DMA_4 = 16,
+	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
+	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
+	/* SGX has 1 ID */
+	OMAP_L3_IA_SGX		= 13,
+	/* CAM has 3 ID */
+	OMAP_L3_IA_CAM_1	= 12,
+	OMAP_L3_IA_CAM_2	= 11,
+	OMAP_L3_IA_CAM_3	= 10,
+	/* DAP has 1 ID */
+	OMAP_L3_IA_DAP		= 9,
+	/* SDMA WR has 2 IDs */
+	OMAP_L3_SDMA_WR_1	= 8,
+	OMAP_L3_SDMA_WR_2	= 7,
+	/* SDMA RD has 4 IDs */
+	OMAP_L3_SDMA_RD_1	= 6,
+	OMAP_L3_SDMA_RD_2	= 5,
+	OMAP_L3_SDMA_RD_3	= 4,
+	OMAP_L3_SDMA_RD_4	= 3,
+	/* HSUSB OTG has 1 ID */
+	OMAP_L3_USBOTG		= 2,
+	/* HSUSB HOST has 1 ID */
+	OMAP_L3_USBHOST		= 1,
+};
+
+enum omap3_l3_code {
+	OMAP_L3_CODE_NOERROR = 0,
+	OMAP_L3_CODE_UNSUP_CMD = 1,
+	OMAP_L3_CODE_ADDR_HOLE = 2,
+	OMAP_L3_CODE_PROTECT_VIOLATION = 3,
+	OMAP_L3_CODE_IN_BAND_ERR = 4,
+	/* codes 5 and 6 are reserved */
+	OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT = 7,
+	OMAP_L3_CODE_REQ_TOUT_NO_RESP = 8,
+	/* codes 9 - 15 are also reserved */
+};
+
+struct omap3_l3 {
+	struct device   *dev;
+	struct clk      *ick;
+
+	/* memory base*/
+	void __iomem    *rt;
+
+	int             debug_irq;
+	int             app_irq;
+
+	/* true when and inband functional error occurs */
+	unsigned        inband:1;
+};
+
+/* offsets for l3 agents in order with the Flag status register */
+unsigned int __iomem omap3_l3_app_bases[] = {
+	/* MPU IA */
+	0x1400,
+	0x1400,
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	0x1800,
+	0x1800,
+	/* SGX IA */
+	0x1c00,
+	0x1c00,
+	/* RESERVED */
+	0,
+	/* CAMERA IA */
+	0x5800,
+	0x5800,
+	0x5800,
+	/* DISPLAY IA */
+	0x5400,
+	0x5400,
+	/* RESERVED */
+	0,
+	/*SDMA RD IA */
+	0x4c00,
+	0x4c00,
+	/* RESERVED */
+	0,
+	/* SDMA WR IA */
+	0x5000,
+	0x5000,
+	/* RESERVED */
+	0,
+	/* USB OTG IA */
+	0x4400,
+	0x4400,
+	0x4400,
+	/* USB HOST IA */
+	0x4000,
+	0x4000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	/* SAD2D IA */
+	0x3000,
+	0x3000,
+	0x3000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	/* SMA TA */
+	0x2000,
+	/* GPMC TA */
+	0x2400,
+	/* OCM RAM TA */
+	0x2800,
+	/* OCM ROM TA */
+	0x2C00,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* IVA 2.2 TA */
+	0x6000,
+	/* SGX TA */
+	0x6400,
+	/* L4 EMU TA */
+	0x7000,
+	/* GPMC TA */
+	0x2400,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* L4 EMU TA */
+	0x7000,
+	/* MAD2D TA */
+	0x3400,
+	/* RESERVED */
+	0,
+	0,
+};
+
+unsigned int __iomem omap3_l3_debug_bases[] = {
+	/* MPU DATA IA */
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	/* DAP IA */
+	0x5c00,
+	0x5c00,
+	/* RESERVED */
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	/* REST RESERVED */
+};
+
+u32 *omap3_l3_bases[] = {
+	omap3_l3_app_bases,
+	omap3_l3_debug_bases,
+};
+
+/*
+ * REVISIT define __raw_readll/__raw_writell here, but move them to
+ * <asm/io.h> at some point
+ */
+#define __raw_writell(v, a)	(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a) = (v))
+#define __raw_readll(a)		(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a))
+
+#endif
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d5a102c..7bb64d8 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -124,7 +124,7 @@
 			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 			sleep_switch = LOWPOWERSTATE_SWITCH;
 		} else {
-			omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
 			pwrdm_wait_transition(pwrdm);
 			sleep_switch = FORCEWAKEUP_SWITCH;
 		}
@@ -140,9 +140,9 @@
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
 		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
-			omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
 		else
-			omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
 		break;
 	case LOWPOWERSTATE_SWITCH:
 		pwrdm_set_lowpwrstchange(pwrdm);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 97feb3a..96907da 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -367,10 +367,10 @@
 	clkdm_clear_all_sleepdeps(clkdm);
 
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
@@ -379,7 +379,10 @@
 	int i, num_mem_banks;
 	struct powerdomain *pwrdm;
 
-	/* Enable autoidle */
+	/*
+	 * Enable autoidle
+	 * XXX This should be handled by hwmod code or PRCM init code
+	 */
 	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
 			  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
@@ -405,11 +408,11 @@
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(dsp_clkdm);
+	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(gfx_clkdm);
+	clkdm_sleep(gfx_clkdm);
 
 	/*
 	 * Clear clockdomain wakeup dependencies and enable
@@ -418,70 +421,6 @@
 	clkdm_for_each(clkdms_setup, NULL);
 	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
 
-	/* Enable clock autoidle for all domains */
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
-			       OMAP24XX_AUTO_MAILBOXES_MASK |
-			       OMAP24XX_AUTO_WDT4_MASK |
-			       OMAP2420_AUTO_WDT3_MASK |
-			       OMAP24XX_AUTO_MSPRO_MASK |
-			       OMAP2420_AUTO_MMC_MASK |
-			       OMAP24XX_AUTO_FAC_MASK |
-			       OMAP2420_AUTO_EAC_MASK |
-			       OMAP24XX_AUTO_HDQ_MASK |
-			       OMAP24XX_AUTO_UART2_MASK |
-			       OMAP24XX_AUTO_UART1_MASK |
-			       OMAP24XX_AUTO_I2C2_MASK |
-			       OMAP24XX_AUTO_I2C1_MASK |
-			       OMAP24XX_AUTO_MCSPI2_MASK |
-			       OMAP24XX_AUTO_MCSPI1_MASK |
-			       OMAP24XX_AUTO_MCBSP2_MASK |
-			       OMAP24XX_AUTO_MCBSP1_MASK |
-			       OMAP24XX_AUTO_GPT12_MASK |
-			       OMAP24XX_AUTO_GPT11_MASK |
-			       OMAP24XX_AUTO_GPT10_MASK |
-			       OMAP24XX_AUTO_GPT9_MASK |
-			       OMAP24XX_AUTO_GPT8_MASK |
-			       OMAP24XX_AUTO_GPT7_MASK |
-			       OMAP24XX_AUTO_GPT6_MASK |
-			       OMAP24XX_AUTO_GPT5_MASK |
-			       OMAP24XX_AUTO_GPT4_MASK |
-			       OMAP24XX_AUTO_GPT3_MASK |
-			       OMAP24XX_AUTO_GPT2_MASK |
-			       OMAP2420_AUTO_VLYNQ_MASK |
-			       OMAP24XX_AUTO_DSS_MASK,
-			       CORE_MOD, CM_AUTOIDLE1);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
-			       OMAP24XX_AUTO_SSI_MASK |
-			       OMAP24XX_AUTO_USB_MASK,
-			       CORE_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
-			       OMAP24XX_AUTO_GPMC_MASK |
-			       OMAP24XX_AUTO_SDMA_MASK,
-			       CORE_MOD, CM_AUTOIDLE3);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
-			       OMAP24XX_AUTO_AES_MASK |
-			       OMAP24XX_AUTO_RNG_MASK |
-			       OMAP24XX_AUTO_SHA_MASK |
-			       OMAP24XX_AUTO_DES_MASK,
-			       CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
-
-	omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
-			       CM_AUTOIDLE);
-
-	/* Put DPLL and both APLLs into autoidle mode */
-	omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_54M_SHIFT),
-			       PLL_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
-			       OMAP24XX_AUTO_WDT1_MASK |
-			       OMAP24XX_AUTO_MPU_WDT_MASK |
-			       OMAP24XX_AUTO_GPIOS_MASK |
-			       OMAP24XX_AUTO_32KSYNC_MASK |
-			       OMAP24XX_AUTO_GPT1_MASK,
-			       WKUP_MOD, CM_AUTOIDLE);
-
 	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 	 * stabilisation */
 	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f864e4..3d6a00e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -496,7 +496,7 @@
 
 	pwrdm_post_transition();
 
-	omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -688,14 +688,11 @@
 
 static void __init prcm_setup_regs(void)
 {
-	u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_AUTO_UART4_MASK : 0;
 	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_EN_UART4_MASK : 0;
 	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_GRPSEL_UART4_MASK : 0;
 
-
 	/* XXX Reset all wkdeps. This should be done when initializing
 	 * powerdomains */
 	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -710,127 +707,10 @@
 	} else
 		omap2_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
-	 */
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_MODEM_MASK |
-		OMAP3430ES2_AUTO_MMC3_MASK |
-		OMAP3430ES2_AUTO_ICR_MASK |
-		OMAP3430_AUTO_AES2_MASK |
-		OMAP3430_AUTO_SHA12_MASK |
-		OMAP3430_AUTO_DES2_MASK |
-		OMAP3430_AUTO_MMC2_MASK |
-		OMAP3430_AUTO_MMC1_MASK |
-		OMAP3430_AUTO_MSPRO_MASK |
-		OMAP3430_AUTO_HDQ_MASK |
-		OMAP3430_AUTO_MCSPI4_MASK |
-		OMAP3430_AUTO_MCSPI3_MASK |
-		OMAP3430_AUTO_MCSPI2_MASK |
-		OMAP3430_AUTO_MCSPI1_MASK |
-		OMAP3430_AUTO_I2C3_MASK |
-		OMAP3430_AUTO_I2C2_MASK |
-		OMAP3430_AUTO_I2C1_MASK |
-		OMAP3430_AUTO_UART2_MASK |
-		OMAP3430_AUTO_UART1_MASK |
-		OMAP3430_AUTO_GPT11_MASK |
-		OMAP3430_AUTO_GPT10_MASK |
-		OMAP3430_AUTO_MCBSP5_MASK |
-		OMAP3430_AUTO_MCBSP1_MASK |
-		OMAP3430ES1_AUTO_FAC_MASK | /* This is es1 only */
-		OMAP3430_AUTO_MAILBOXES_MASK |
-		OMAP3430_AUTO_OMAPCTRL_MASK |
-		OMAP3430ES1_AUTO_FSHOSTUSB_MASK |
-		OMAP3430_AUTO_HSOTGUSB_MASK |
-		OMAP3430_AUTO_SAD2D_MASK |
-		OMAP3430_AUTO_SSI_MASK,
-		CORE_MOD, CM_AUTOIDLE1);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_PKA_MASK |
-		OMAP3430_AUTO_AES1_MASK |
-		OMAP3430_AUTO_RNG_MASK |
-		OMAP3430_AUTO_SHA11_MASK |
-		OMAP3430_AUTO_DES1_MASK,
-		CORE_MOD, CM_AUTOIDLE2);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430_AUTO_MAD2D_MASK |
-			OMAP3430ES2_AUTO_USBTLL_MASK,
-			CORE_MOD, CM_AUTOIDLE3);
-	}
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_WDT2_MASK |
-		OMAP3430_AUTO_WDT1_MASK |
-		OMAP3430_AUTO_GPIO1_MASK |
-		OMAP3430_AUTO_32KSYNC_MASK |
-		OMAP3430_AUTO_GPT12_MASK |
-		OMAP3430_AUTO_GPT1_MASK,
-		WKUP_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_DSS_MASK,
-		OMAP3430_DSS_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_CAM_MASK,
-		OMAP3430_CAM_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		omap3630_auto_uart4_mask |
-		OMAP3430_AUTO_GPIO6_MASK |
-		OMAP3430_AUTO_GPIO5_MASK |
-		OMAP3430_AUTO_GPIO4_MASK |
-		OMAP3430_AUTO_GPIO3_MASK |
-		OMAP3430_AUTO_GPIO2_MASK |
-		OMAP3430_AUTO_WDT3_MASK |
-		OMAP3430_AUTO_UART3_MASK |
-		OMAP3430_AUTO_GPT9_MASK |
-		OMAP3430_AUTO_GPT8_MASK |
-		OMAP3430_AUTO_GPT7_MASK |
-		OMAP3430_AUTO_GPT6_MASK |
-		OMAP3430_AUTO_GPT5_MASK |
-		OMAP3430_AUTO_GPT4_MASK |
-		OMAP3430_AUTO_GPT3_MASK |
-		OMAP3430_AUTO_GPT2_MASK |
-		OMAP3430_AUTO_MCBSP4_MASK |
-		OMAP3430_AUTO_MCBSP3_MASK |
-		OMAP3430_AUTO_MCBSP2_MASK,
-		OMAP3430_PER_MOD,
-		CM_AUTOIDLE);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430ES2_AUTO_USBHOST_MASK,
-			OMAP3430ES2_USBHOST_MOD,
-			CM_AUTOIDLE);
-	}
-
+	/* XXX This should be handled by hwmod code or SCM init code */
 	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
 
 	/*
-	 * Set all plls to autoidle. This is needed until autoidle is
-	 * enabled by clockfw
-	 */
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
-			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
-			 MPU_MOD,
-			 CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
-			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
-			 PLL_MOD,
-			 CM_AUTOIDLE);
-	omap2_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.
@@ -990,10 +870,10 @@
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index eaed0df..a11be81 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -2,7 +2,7 @@
  * OMAP powerdomain control
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -938,3 +938,44 @@
 
 	return count;
 }
+
+/**
+ * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
+ * @pwrdm: struct powerdomain *
+ *
+ * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
+ * can lose either memory or logic context or if @pwrdm is invalid, or
+ * returns 0 otherwise.  This function is not concerned with how the
+ * powerdomain registers are programmed (i.e., to go off or not); it's
+ * concerned with whether it's ever possible for this powerdomain to
+ * go off while some other part of the chip is active.  This function
+ * assumes that every powerdomain can go to either ON or INACTIVE.
+ */
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
+{
+	int i;
+
+	if (IS_ERR_OR_NULL(pwrdm)) {
+		pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
+			 __func__);
+		return 1;
+	}
+
+	if (pwrdm->pwrsts & PWRSTS_OFF)
+		return 1;
+
+	if (pwrdm->pwrsts & PWRSTS_RET) {
+		if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
+			return 1;
+
+		for (i = 0; i < pwrdm->banks; i++)
+			if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
+				return 1;
+	}
+
+	for (i = 0; i < pwrdm->banks; i++)
+		if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
+			return 1;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index c66431e..027f40b 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -2,7 +2,7 @@
  * OMAP2/3/4 powerdomain control
  *
  * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -34,17 +34,14 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON		(1 << PWRDM_POWER_ON)
+#define PWRSTS_INACTIVE		(1 << PWRDM_POWER_INACTIVE)
+#define PWRSTS_RET		(1 << PWRDM_POWER_RET)
 #define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
-#define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_ON))
 
-#define PWRSTS_OFF_RET		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_RET))
-
-#define PWRSTS_RET_ON		((1 << PWRDM_POWER_RET) | \
-				 (1 << PWRDM_POWER_ON))
-
-#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
+#define PWRSTS_OFF_ON		(PWRSTS_OFF | PWRSTS_ON)
+#define PWRSTS_OFF_RET		(PWRSTS_OFF | PWRSTS_RET)
+#define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
+#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
 
 /* Powerdomain flags */
@@ -165,7 +162,6 @@
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_fw_init(void);
 void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
 
 struct powerdomain *pwrdm_lookup(const char *name);
@@ -212,6 +208,7 @@
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap2xxx_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index 5b4dd97..4210c33 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP2/3 common powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
  *
@@ -62,13 +62,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -76,4 +76,5 @@
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+	.pwrsts		= PWRSTS_ON,
 };
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index 78739e1..cc389fb 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP2XXX powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
  *
@@ -30,13 +30,13 @@
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -48,10 +48,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -87,13 +87,13 @@
 	.prcm_offs	  = OMAP2430_MDM_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index e1bec56..9c9c113 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP3 powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
  *
@@ -47,10 +47,10 @@
 		[3] = PWRSTS_OFF_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-		[1] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
+		[1] = PWRSTS_ON,
 		[2] = PWRSTS_OFF_ON,
-		[3] = PWRDM_POWER_ON,
+		[3] = PWRSTS_ON,
 	},
 };
 
@@ -128,13 +128,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -149,13 +149,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -164,13 +164,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -182,10 +182,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -200,7 +200,7 @@
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -208,7 +208,7 @@
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
 	 * REVISIT: Enabling usb host save and restore mechanism seems to
 	 * leave the usb host domain permanently in ACTIVE mode after
@@ -218,10 +218,10 @@
 	/*.flags	  = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index 26d7641..c4222c7 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -2,7 +2,7 @@
  * OMAP4 Power domains framework
  *
  * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
  * Benoit Cousson (b-cousson@ti.com)
@@ -40,18 +40,18 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* core_nret_bank */
+		[0] = PWRSTS_OFF,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_RET,	/* core_other_bank */
+		[2] = PWRSTS_RET,	/* core_other_bank */
 		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
 		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* core_nret_bank */
+		[0] = PWRSTS_ON,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_ON,	/* core_other_bank */
-		[3] = PWRDM_POWER_ON,	/* ducati_l2ram */
-		[4] = PWRDM_POWER_ON,	/* ducati_unicache */
+		[2] = PWRSTS_ON,	/* core_other_bank */
+		[3] = PWRSTS_ON,	/* ducati_l2ram */
+		[4] = PWRSTS_ON,	/* ducati_unicache */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -65,10 +65,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* gfx_mem */
+		[0] = PWRSTS_OFF,	/* gfx_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* gfx_mem */
+		[0] = PWRSTS_ON,	/* gfx_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -80,15 +80,15 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* aessmem */
-		[1] = PWRDM_POWER_OFF,	/* periphmem */
+		[0] = PWRSTS_RET,	/* aessmem */
+		[1] = PWRSTS_OFF,	/* periphmem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* aessmem */
-		[1] = PWRDM_POWER_ON,	/* periphmem */
+		[0] = PWRSTS_ON,	/* aessmem */
+		[1] = PWRSTS_ON,	/* periphmem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -103,10 +103,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* dss_mem */
+		[0] = PWRSTS_OFF,	/* dss_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* dss_mem */
+		[0] = PWRSTS_ON,	/* dss_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -121,14 +121,14 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* tesla_edma */
+		[0] = PWRSTS_RET,	/* tesla_edma */
 		[1] = PWRSTS_OFF_RET,	/* tesla_l1 */
 		[2] = PWRSTS_OFF_RET,	/* tesla_l2 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* tesla_edma */
-		[1] = PWRDM_POWER_ON,	/* tesla_l1 */
-		[2] = PWRDM_POWER_ON,	/* tesla_l2 */
+		[0] = PWRSTS_ON,	/* tesla_edma */
+		[1] = PWRSTS_ON,	/* tesla_l1 */
+		[2] = PWRSTS_ON,	/* tesla_l2 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -142,10 +142,10 @@
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* wkup_bank */
+		[0] = PWRSTS_OFF,	/* wkup_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* wkup_bank */
+		[0] = PWRSTS_ON,	/* wkup_bank */
 	},
 };
 
@@ -162,7 +162,7 @@
 		[0] = PWRSTS_OFF_RET,	/* cpu0_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu0_l1 */
+		[0] = PWRSTS_ON,	/* cpu0_l1 */
 	},
 };
 
@@ -179,7 +179,7 @@
 		[0] = PWRSTS_OFF_RET,	/* cpu1_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu1_l1 */
+		[0] = PWRSTS_ON,	/* cpu1_l1 */
 	},
 };
 
@@ -192,10 +192,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* emu_bank */
+		[0] = PWRSTS_OFF,	/* emu_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* emu_bank */
+		[0] = PWRSTS_ON,	/* emu_bank */
 	},
 };
 
@@ -211,12 +211,12 @@
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
 		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
-		[2] = PWRDM_POWER_RET,	/* mpu_ram */
+		[2] = PWRSTS_RET,	/* mpu_ram */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* mpu_l1 */
-		[1] = PWRDM_POWER_ON,	/* mpu_l2 */
-		[2] = PWRDM_POWER_ON,	/* mpu_ram */
+		[0] = PWRSTS_ON,	/* mpu_l1 */
+		[1] = PWRSTS_ON,	/* mpu_l2 */
+		[2] = PWRSTS_ON,	/* mpu_ram */
 	},
 };
 
@@ -227,19 +227,19 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* hwa_mem */
+		[0] = PWRSTS_OFF,	/* hwa_mem */
 		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
 		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
 		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* hwa_mem */
-		[1] = PWRDM_POWER_ON,	/* sl2_mem */
-		[2] = PWRDM_POWER_ON,	/* tcm1_mem */
-		[3] = PWRDM_POWER_ON,	/* tcm2_mem */
+		[0] = PWRSTS_ON,	/* hwa_mem */
+		[1] = PWRSTS_ON,	/* sl2_mem */
+		[2] = PWRSTS_ON,	/* tcm1_mem */
+		[3] = PWRSTS_ON,	/* tcm2_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -253,10 +253,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* cam_mem */
+		[0] = PWRSTS_OFF,	/* cam_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cam_mem */
+		[0] = PWRSTS_ON,	/* cam_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -271,10 +271,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* l3init_bank1 */
+		[0] = PWRSTS_OFF,	/* l3init_bank1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* l3init_bank1 */
+		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -289,12 +289,12 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* nonretained_bank */
-		[1] = PWRDM_POWER_RET,	/* retained_bank */
+		[0] = PWRSTS_OFF,	/* nonretained_bank */
+		[1] = PWRSTS_RET,	/* retained_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* nonretained_bank */
-		[1] = PWRDM_POWER_ON,	/* retained_bank */
+		[0] = PWRSTS_ON,	/* nonretained_bank */
+		[1] = PWRSTS_ON,	/* retained_bank */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
index 3300ff6..d22d1b4 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.h
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -38,8 +38,8 @@
 #define OMAP4430_PRCM_MPU_CPU1_INST		0x0800
 
 /* PRCM_MPU clockdomain register offsets (from instance start) */
-#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS	0x0018
-#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS	0x0018
 
 
 /*
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index fc62fb5..c9122dd 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -37,14 +37,16 @@
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
+	if (!arch_clock || !arch_clock->clk_enable)
+		return -EINVAL;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_enable)
-		ret = arch_clock->clk_enable(clk);
+	ret = arch_clock->clk_enable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -58,6 +60,9 @@
 	if (clk == NULL || IS_ERR(clk))
 		return;
 
+	if (!arch_clock || !arch_clock->clk_disable)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
 		pr_err("Trying disable clock %s with 0 usecount\n",
@@ -66,8 +71,7 @@
 		goto out;
 	}
 
-	if (arch_clock->clk_disable)
-		arch_clock->clk_disable(clk);
+	arch_clock->clk_disable(clk);
 
 out:
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -77,7 +81,7 @@
 unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
-	unsigned long ret = 0;
+	unsigned long ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return 0;
@@ -97,14 +101,16 @@
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
-	long ret = 0;
+	long ret;
 
 	if (clk == NULL || IS_ERR(clk))
-		return ret;
+		return 0;
+
+	if (!arch_clock || !arch_clock->clk_round_rate)
+		return 0;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_round_rate)
-		ret = arch_clock->clk_round_rate(clk, rate);
+	ret = arch_clock->clk_round_rate(clk, rate);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -119,14 +125,13 @@
 	if (clk == NULL || IS_ERR(clk))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_rate)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_rate)
-		ret = arch_clock->clk_set_rate(clk, rate);
-	if (ret == 0) {
-		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+	ret = arch_clock->clk_set_rate(clk, rate);
+	if (ret == 0)
 		propagate_rate(clk);
-	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -141,15 +146,14 @@
 	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_parent)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
-		if (arch_clock->clk_set_parent)
-			ret = arch_clock->clk_set_parent(clk, parent);
-		if (ret == 0) {
-			if (clk->recalc)
-				clk->rate = clk->recalc(clk);
+		ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0)
 			propagate_rate(clk);
-		}
 	} else
 		ret = -EBUSY;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -335,6 +339,38 @@
 	return ret;
 }
 
+int omap_clk_enable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->allow_idle)
+			c->ops->allow_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
+int omap_clk_disable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->deny_idle)
+			c->ops->deny_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
 /*
  * Low level helpers
  */
@@ -367,9 +403,11 @@
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_init_cpufreq_table)
-		arch_clock->clk_init_cpufreq_table(table);
+	arch_clock->clk_init_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 
@@ -377,9 +415,11 @@
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_exit_cpufreq_table)
-		arch_clock->clk_exit_cpufreq_table(table);
+	arch_clock->clk_exit_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 #endif
@@ -397,6 +437,9 @@
 	struct clk *ck;
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_disable_unused)
+		return 0;
+
 	pr_info("clock: disabling unused clocks to save power\n");
 	list_for_each_entry(ck, &clocks, node) {
 		if (ck->ops == &clkops_null)
@@ -406,14 +449,14 @@
 			continue;
 
 		spin_lock_irqsave(&clockfw_lock, flags);
-		if (arch_clock->clk_disable_unused)
-			arch_clock->clk_disable_unused(ck);
+		arch_clock->clk_disable_unused(ck);
 		spin_unlock_irqrestore(&clockfw_lock, flags);
 	}
 
 	return 0;
 }
 late_initcall(clk_disable_unused);
+late_initcall(omap_clk_enable_autoidle_all);
 #endif
 
 int __init clk_init(struct clk_functions * custom_clocks)
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 1d706cf..ee9f6eb 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -342,6 +342,10 @@
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
+	/* Enable autoidle on OMAP2 / OMAP3 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		l |= 0x1 << 0;
+
 	/*
 	 * Enable wake-up on OMAP2 CPUs.
 	 */
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index d43e623..006e599 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -25,6 +25,8 @@
  * @disable: fn ptr that enables the current clock in hardware
  * @find_idlest: function returning the IDLEST register for the clock's IP blk
  * @find_companion: function returning the "companion" clk reg for the clock
+ * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
+ * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
  *
  * A "companion" clk is an accompanying clock to the one being queried
  * that must be enabled for the IP module connected to the clock to
@@ -42,6 +44,8 @@
 					       u8 *, u8 *);
 	void			(*find_companion)(struct clk *, void __iomem **,
 						  u8 *);
+	void			(*allow_idle)(struct clk *);
+	void			(*deny_idle)(struct clk *);
 };
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -105,7 +109,6 @@
  * @clk_ref: struct clk pointer to the clock's reference clock input
  * @control_reg: register containing the DPLL mode bitfield
  * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @rate_tolerance: maximum variance allowed from target rate (in Hz)
  * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
  * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
  * @max_multiplier: maximum valid non-bypass multiplier value (actual)
@@ -131,12 +134,9 @@
  * XXX Some DPLLs have multiple bypass inputs, so it's not technically
  * correct to only have one @clk_bypass pointer.
  *
- * XXX @rate_tolerance should probably be deprecated - currently there
- * don't seem to be any usecases for DPLL rounding that is not exact.
- *
  * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
  * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a differenct structure, so that the runtime-fixed data
+ * and placed into a different structure, so that the runtime-fixed data
  * can be placed into read-only space.
  */
 struct dpll_data {
@@ -147,7 +147,6 @@
 	struct clk		*clk_ref;
 	void __iomem		*control_reg;
 	u32			enable_mask;
-	unsigned int		rate_tolerance;
 	unsigned long		last_rounded_rate;
 	u16			last_rounded_m;
 	u16			max_multiplier;
@@ -172,12 +171,24 @@
 
 #endif
 
-/* struct clk.flags possibilities */
+/*
+ * struct clk.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
 #define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
 #define CLOCK_IDLE_CONTROL	(1 << 1)
 #define CLOCK_NO_IDLE_PARENT	(1 << 2)
 #define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
 #define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2		(1 << 5)
 
 /**
  * struct clk - OMAP struct clk
@@ -293,6 +304,8 @@
 extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
 #endif
 extern struct clk *omap_clk_get_by_name(const char *name);
+extern int omap_clk_enable_autoidle_all(void);
+extern int omap_clk_disable_autoidle_all(void);
 
 extern const struct clkops clkops_null;
 
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 1b91168..d779283 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -315,6 +315,8 @@
 #define INT_34XX_SSM_ABORT_IRQ	6
 #define INT_34XX_SYS_NIRQ	7
 #define INT_34XX_D2D_FW_IRQ	8
+#define INT_34XX_L3_DBG_IRQ     9
+#define INT_34XX_L3_APP_IRQ     10
 #define INT_34XX_PRCM_MPU_IRQ	11
 #define INT_34XX_MCBSP1_IRQ	16
 #define INT_34XX_MCBSP2_IRQ	17
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 97aa8e7..8a1368f 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -561,6 +561,7 @@
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
 int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
 
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
@@ -595,6 +596,8 @@
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 57adb27..9bbda9a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -83,9 +83,11 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
+#include <plat/clock.h>
 
 /* These parameters are passed to _omap_device_{de,}activate() */
 #define USE_WAKEUP_LAT			0
@@ -239,12 +241,12 @@
 }
 
 /**
- * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
  * @od: struct omap_device *od
  *
  * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
- * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
+ * if it does not exist already.
  *
  * The function is called from inside omap_device_build_ss(), after
  * omap_device_register.
@@ -254,25 +256,39 @@
  *
  * No return value.
  */
-static void _add_optional_clock_alias(struct omap_device *od,
+static void _add_optional_clock_clkdev(struct omap_device *od,
 				      struct omap_hwmod *oh)
 {
 	int i;
 
 	for (i = 0; i < oh->opt_clks_cnt; i++) {
 		struct omap_hwmod_opt_clk *oc;
-		int r;
+		struct clk *r;
+		struct clk_lookup *l;
 
 		oc = &oh->opt_clks[i];
 
 		if (!oc->_clk)
 			continue;
 
-		r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
-				  (char *)oc->clk, &od->pdev.dev);
-		if (r)
-			pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+		r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
+		if (!IS_ERR(r))
+			continue; /* clkdev entry exists */
+
+		r = omap_clk_get_by_name((char *)oc->clk);
+		if (IS_ERR(r)) {
+			pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+			       dev_name(&od->pdev.dev), oc->clk);
+			continue;
+		}
+
+		l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
+		if (!l) {
+			pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
 			       dev_name(&od->pdev.dev), oc->role);
+			return;
+		}
+		clkdev_add(l);
 	}
 }
 
@@ -480,7 +496,7 @@
 
 	for (i = 0; i < oh_cnt; i++) {
 		hwmods[i]->od = od;
-		_add_optional_clock_alias(od, hwmods[i]);
+		_add_optional_clock_clkdev(od, hwmods[i]);
 	}
 
 	if (ret)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 191332b..158c0ee 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2117,14 +2117,14 @@
 	/* we start off in DISABLED state */
 	host->dpm_state = DISABLED;
 
-	if (mmc_host_enable(host->mmc) != 0) {
+	if (clk_enable(host->iclk) != 0) {
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
 	}
 
-	if (clk_enable(host->iclk) != 0) {
-		mmc_host_disable(host->mmc);
+	if (mmc_host_enable(host->mmc) != 0) {
+		clk_disable(host->iclk);
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 3dd4971..2b4acb8 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -124,6 +124,8 @@
 	u32 pre_margin = GET_WLDR_VAL(timer_margin);
 	void __iomem *base = wdev->base;
 
+	pm_runtime_get_sync(wdev->dev);
+
 	/* just count up at 32 KHz */
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
 		cpu_relax();
@@ -131,6 +133,8 @@
 	__raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
 		cpu_relax();
+
+	pm_runtime_put_sync(wdev->dev);
 }
 
 /*
@@ -160,6 +164,8 @@
 	omap_wdt_ping(wdev); /* trigger loading of new timeout value */
 	omap_wdt_enable(wdev);
 
+	pm_runtime_put_sync(wdev->dev);
+
 	return nonseekable_open(inode, file);
 }
 
@@ -171,6 +177,7 @@
 	 *      Shut off the timer unless NOWAYOUT is defined.
 	 */
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
+	pm_runtime_get_sync(wdev->dev);
 
 	omap_wdt_disable(wdev);
 
@@ -190,9 +197,11 @@
 
 	/* Refresh LOAD_TIME. */
 	if (len) {
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 	}
 	return len;
 }
@@ -224,15 +233,18 @@
 			return put_user(omap_prcm_get_reset_sources(),
 					(int __user *)arg);
 	case WDIOC_KEEPALIVE:
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 		return 0;
 	case WDIOC_SETTIMEOUT:
 		if (get_user(new_margin, (int __user *)arg))
 			return -EFAULT;
 		omap_wdt_adjust_timeout(new_margin);
 
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_disable(wdev);
 		omap_wdt_set_timeout(wdev);
@@ -240,6 +252,7 @@
 
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 		/* Fall */
 	case WDIOC_GETTIMEOUT:
 		return put_user(timer_margin, (int __user *)arg);
@@ -345,8 +358,11 @@
 {
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
-	if (wdev->omap_wdt_users)
+	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_disable(wdev);
+		pm_runtime_put_sync(wdev->dev);
+	}
 }
 
 static int __devexit omap_wdt_remove(struct platform_device *pdev)
@@ -381,8 +397,11 @@
 {
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
-	if (wdev->omap_wdt_users)
+	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_disable(wdev);
+		pm_runtime_put_sync(wdev->dev);
+	}
 
 	return 0;
 }
@@ -392,8 +411,10 @@
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
 	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_enable(wdev);
 		omap_wdt_ping(wdev);
+		pm_runtime_put_sync(wdev->dev);
 	}
 
 	return 0;