[PATCH 12/29] ARM: omap4: clk: Convert to common clk

Rajendra Nayak rnayak at ti.com
Thu Jun 14 08:47:01 EDT 2012


Convert all OMAP4 specific platform files to use COMMON clk
and keep all the changes under the CONFIG_COMMON_CLK macro check
so it does not break any existing code. At a later point switch
to COMMON clk and get rid of all old/legacy code.

This converts all apis which will be called directly from COMMON
clk to take a struct clk_hw parameter, and all the internal platform
apis to take a struct clk_hw_omap parameter.

Changes are based off the original patch from Mike Turquette.

Signed-off-by: Rajendra Nayak <rnayak at ti.com>
---
 arch/arm/mach-omap2/clkt_clksel.c |  144 +++++++++++++++++++++++++-
 arch/arm/mach-omap2/clkt_dpll.c   |   54 ++++++++++-
 arch/arm/mach-omap2/clkt_iclk.c   |    4 +
 arch/arm/mach-omap2/clock.c       |  200 +++++++++++++++++++++++++++++++++++--
 arch/arm/mach-omap2/clock.h       |   60 +++++++++++-
 arch/arm/mach-omap2/dpll3xxx.c    |  198 ++++++++++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/dpll44xx.c    |   37 +++++++
 7 files changed, 681 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 1c054ba..c99222a 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -41,7 +41,11 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk-provider.h>
+#else
 #include <linux/clk.h>
+#endif
 #include <linux/io.h>
 #include <linux/bug.h>
 
@@ -60,11 +64,18 @@
  * the element associated with the supplied parent clock address.
  * Returns a pointer to the struct clksel on success or NULL on error.
  */
+#ifdef CONFIG_COMMON_CLK
+static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
+#else
 static const struct clksel *_get_clksel_by_parent(struct clk *clk,
+#endif
 						  struct clk *src_clk)
 {
 	const struct clksel *clks;
 
+	if (!src_clk)
+		return NULL;
+
 	for (clks = clk->clksel; clks->parent; clks++)
 		if (clks->parent == src_clk)
 			break; /* Found the requested parent */
@@ -74,7 +85,11 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
 		WARN(1, "clock: Could not find parent clock %s in clksel array "
 		     "of clock %s\n",
 		      __clk_get_name(src_clk),
+#ifdef CONFIG_COMMON_CLK
+		      __clk_get_name(clk->hw.clk));
+#else
 		      __clk_get_name(clk));
+#endif
 		return NULL;
 	}
 
@@ -96,6 +111,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
  * success (in this latter case, the corresponding register bitfield
  * value is passed back in the variable pointed to by @field_val)
  */
+#ifndef CONFIG_COMMON_CLK
 static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
 				u32 *field_val)
 {
@@ -138,6 +154,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
 
 	return max_div;
 }
+#endif
 
 /**
  * _write_clksel_reg() - program a clock's clksel register in hardware
@@ -152,7 +169,11 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
  * take into account any time the hardware might take to switch the
  * clock source.
  */
+#ifdef CONFIG_COMMON_CLK
+static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
+#else
 static void _write_clksel_reg(struct clk *clk, u32 field_val)
+#endif
 {
 	u32 v;
 
@@ -175,13 +196,22 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
  * before calling.  Returns 0 on error or returns the actual integer divisor
  * upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
+#else
 static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
+#endif
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 	struct clk *parent;
 
+#ifdef CONFIG_COMMON_CLK
+	parent = __clk_get_parent(clk->hw.clk);
+#else
 	parent = __clk_get_parent(clk);
+#endif
+
 	clks = _get_clksel_by_parent(clk, parent);
 	if (!clks)
 		return 0;
@@ -198,7 +228,11 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
 		/* This indicates a data error */
 		WARN(1, "clock: Could not find fieldval %d for clock %s parent "
 		     "%s\n", field_val,
+#ifdef CONFIG_COMMON_CLK
+		     __clk_get_name(clk->hw.clk),
+#else
 		     __clk_get_name(clk),
+#endif
 		     __clk_get_name(parent));
 		return 0;
 	}
@@ -216,7 +250,11 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
  * register field value _before_ left-shifting (i.e., LSB is at bit
  * 0); or returns 0xFFFFFFFF (~0) upon error.
  */
+#ifdef CONFIG_COMMON_CLK
+static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
+#else
 static u32 _divisor_to_clksel(struct clk *clk, u32 div)
+#endif
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
@@ -225,7 +263,11 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 	/* should never happen */
 	WARN_ON(div == 0);
 
+#ifdef CONFIG_COMMON_CLK
+	parent = __clk_get_parent(clk->hw.clk);
+#else
 	parent = __clk_get_parent(clk);
+#endif
 	clks = _get_clksel_by_parent(clk, parent);
 	if (!clks)
 		return ~0;
@@ -241,7 +283,11 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 	if (!clkr->div) {
 		pr_err("clock: Could not find divisor %d for clock %s parent "
 		       "%s\n", div,
+#ifdef CONFIG_COMMON_CLK
+		       __clk_get_name(clk->hw.clk),
+#else
 		       __clk_get_name(clk),
+#endif
 		       __clk_get_name(parent));
 		return ~0;
 	}
@@ -257,7 +303,11 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
  * into the hardware, convert it into the actual divisor value, and
  * return it; or return 0 on error.
  */
+#ifdef CONFIG_COMMON_CLK
+static u32 _read_divisor(struct clk_hw_omap *clk)
+#else
 static u32 _read_divisor(struct clk *clk)
+#endif
 {
 	u32 v;
 
@@ -285,7 +335,12 @@ static u32 _read_divisor(struct clk *clk)
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
+#ifdef CONFIG_COMMON_CLK
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
+						 unsigned long target_rate,
+#else
 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
+#endif
 				u32 *new_div)
 {
 	unsigned long test_rate;
@@ -296,9 +351,14 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 	unsigned long parent_rate;
 	const char *clk_name;
 
+#ifdef CONFIG_COMMON_CLK
+	parent = __clk_get_parent(clk->hw.clk);
+	clk_name = __clk_get_name(clk->hw.clk);
+#else
 	parent = __clk_get_parent(clk);
-	parent_rate = __clk_get_rate(parent);
 	clk_name = __clk_get_name(clk);
+#endif
+	parent_rate = __clk_get_rate(parent);
 
 	if (!clk->clksel || !clk->clksel_mask)
 		return ~0;
@@ -358,8 +418,14 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
  * to.  Update @clk's .parent field with the appropriate clk ptr.  No
  * return value.
  */
+#ifdef CONFIG_COMMON_CLK
+u8 omap2_init_clksel_parent(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 void omap2_init_clksel_parent(struct clk *clk)
 {
+#endif
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 	u32 r, found = 0;
@@ -367,10 +433,17 @@ void omap2_init_clksel_parent(struct clk *clk)
 	const char *clk_name;
 
 	if (!clk->clksel || !clk->clksel_mask)
+#ifdef CONFIG_COMMON_CLK
+		return -EINVAL;
+
+	parent = __clk_get_parent(hw->clk);
+	clk_name = __clk_get_name(hw->clk);
+#else
 		return;
 
 	parent = __clk_get_parent(clk);
 	clk_name = __clk_get_name(clk);
+#endif
 
 	r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
 	r >>= __ffs(clk->clksel_mask);
@@ -389,9 +462,14 @@ void omap2_init_clksel_parent(struct clk *clk)
 						 ((parent) ?
 						  __clk_get_name(parent) :
 						 "NULL"));
+#ifdef CONFIG_COMMON_CLK
+				};
+				return r;
+#else
 					clk_reparent(clk, clks->parent);
 				};
 				found = 1;
+#endif
 			}
 		}
 	}
@@ -400,7 +478,11 @@ void omap2_init_clksel_parent(struct clk *clk)
 	WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
 	     clk_name, r);
 
+#ifdef CONFIG_COMMON_CLK
+	return -ENODEV;
+#else
 	return;
+#endif
 }
 
 /**
@@ -412,6 +494,28 @@ void omap2_init_clksel_parent(struct clk *clk)
  * function.  Returns the clock's current rate, based on its parent's rate
  * and its current divisor setting in the hardware.
  */
+#ifdef CONFIG_COMMON_CLK
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
+{
+	unsigned long rate;
+	u32 div = 0;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
+	if (!parent_rate)
+		return 0;
+
+	div = _read_divisor(clk);
+	if (!div)
+		rate = parent_rate;
+	else
+		rate = parent_rate / div;
+
+	pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
+			__clk_get_name(hw->clk), rate, div);
+
+	return rate;
+}
+#else
 unsigned long omap2_clksel_recalc(struct clk *clk)
 {
 	unsigned long rate;
@@ -431,6 +535,7 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
 
 	return rate;
 }
+#endif
 
 /**
  * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
@@ -443,8 +548,15 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
+#ifdef CONFIG_COMMON_CLK
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			unsigned long *parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
 {
+#endif
 	u32 new_div;
 
 	return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
@@ -465,8 +577,15 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
  * is changed, they will all be affected without any notification.
  * Returns -EINVAL upon error, or 0 upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 {
+#endif
 	u32 field_val, validrate, new_div = 0;
 
 	if (!clk->clksel || !clk->clksel_mask)
@@ -482,12 +601,16 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 
 	_write_clksel_reg(clk, field_val);
 
-	clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
-
 	pr_debug("clock: %s: set rate to %ld\n",
+#ifdef CONFIG_COMMON_CLK
+				__clk_get_name(hw->clk),
+				__clk_get_rate(hw->clk));
+#else
 				__clk_get_name(clk),
 				__clk_get_rate(clk));
 
+	clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
+#endif
 	return 0;
 }
 
@@ -511,6 +634,18 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
  * affected without any notification.  Returns -EINVAL upon error, or
  * 0 upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
+	if (!clk->clksel || !clk->clksel_mask)
+		return -EINVAL;
+
+	_write_clksel_reg(clk, field_val);
+	return 0;
+}
+#else
 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
 {
 	u32 field_val = 0;
@@ -522,7 +657,6 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
 	parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
 	if (!parent_div)
 		return -EINVAL;
-
 	_write_clksel_reg(clk, field_val);
 
 	clk_reparent(clk, new_parent);
@@ -532,7 +666,6 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
 
 	if (parent_div > 0)
 		__clk_get_rate(clk) /= parent_div;
-
 	pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
 		 __clk_get_name(clk),
 		 __clk_get_name(__clk_get_parent(clk)),
@@ -540,3 +673,4 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
 
 	return 0;
 }
+#endif
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 6a8a012..e84512f 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -16,7 +16,11 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk-provider.h>
+#else
 #include <linux/clk.h>
+#endif
 #include <linux/io.h>
 
 #include <asm/div64.h>
@@ -78,7 +82,11 @@
  * (assuming that it is counting N upwards), or -2 if the enclosing loop
  * should skip to the next iteration (again assuming N is increasing).
  */
+#ifdef CONFIG_COMMON_CLK
+static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
+#else
 static int _dpll_test_fint(struct clk *clk, u8 n)
+#endif
 {
 	struct dpll_data *dd;
 	long fint, fint_min, fint_max;
@@ -87,7 +95,11 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
 	dd = clk->dpll_data;
 
 	/* DPLL divider must result in a valid jitter correction val */
+#ifdef CONFIG_COMMON_CLK
+	fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
+#else
 	fint = __clk_get_rate(__clk_get_parent(clk)) / n;
+#endif
 
 	if (cpu_is_omap24xx()) {
 		/* Should not be called for OMAP2, so warn if it is called */
@@ -188,15 +200,24 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
 }
 
 /* Public functions */
-
+#ifdef CONFIG_COMMON_CLK
+u8 omap2_init_dpll_parent(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 void omap2_init_dpll_parent(struct clk *clk)
 {
+#endif
 	u32 v;
 	struct dpll_data *dd;
 
 	dd = clk->dpll_data;
 	if (!dd)
+#ifdef CONFIG_COMMON_CLK
+		return -EINVAL;
+#else
 		return;
+#endif
 
 	v = __raw_readl(dd->control_reg);
 	v &= dd->enable_mask;
@@ -206,18 +227,34 @@ void omap2_init_dpll_parent(struct clk *clk)
 	if (cpu_is_omap24xx()) {
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
+#ifdef CONFIG_COMMON_CLK
+			return 1;
+#else
 			clk_reparent(clk, dd->clk_bypass);
+#endif
 	} else if (cpu_is_omap34xx()) {
 		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
+#ifdef CONFIG_COMMON_CLK
+			return 1;
+#else
 			clk_reparent(clk, dd->clk_bypass);
+#endif
 	} else if (cpu_is_omap44xx()) {
 		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
+#ifdef CONFIG_COMMON_CLK
+			return 1;
+#else
 			clk_reparent(clk, dd->clk_bypass);
+#endif
 	}
+#ifdef CONFIG_COMMON_CLK
+	return 0;
+#else
 	return;
+#endif
 }
 
 /**
@@ -234,7 +271,11 @@ void omap2_init_dpll_parent(struct clk *clk)
  * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
  * if the clock @clk is not a DPLL.
  */
+#ifdef CONFIG_COMMON_CLK
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
+#else
 u32 omap2_get_dpll_rate(struct clk *clk)
+#endif
 {
 	long long dpll_clk;
 	u32 dpll_mult, dpll_div, v;
@@ -290,8 +331,15 @@ u32 omap2_get_dpll_rate(struct clk *clk)
  * (expensive) function again.  Returns ~0 if the target rate cannot
  * be rounded, or the rounded rate upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+		unsigned long *parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 {
+#endif
 	int m, n, r, scaled_max_m;
 	unsigned long scaled_rt_rp;
 	unsigned long new_rate = 0;
@@ -305,7 +353,11 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 	dd = clk->dpll_data;
 
 	ref_rate = __clk_get_rate(dd->clk_ref);
+#ifdef CONFIG_COMMON_CLK
+	clk_name = __clk_get_name(hw->clk);
+#else
 	clk_name = __clk_get_name(clk);
+#endif
 	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
 		 clk_name, target_rate);
 
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index 3d43fba..7787fbb 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -11,7 +11,11 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk-provider.h>
+#else
 #include <linux/clk.h>
+#endif
 #include <linux/io.h>
 
 #include <plat/clock.h>
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index aa00f72..42cdd9f 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -19,7 +19,11 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk-provider.h>
+#else
 #include <linux/clk.h>
+#endif
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <trace/events/power.h>
@@ -45,6 +49,30 @@ u16 cpu_mask;
  */
 static bool clkdm_control = true;
 
+#ifdef CONFIG_COMMON_CLK
+
+/*
+ * Used for clocks that have the same value as the parent clock,
+ * divided by some factor
+ */
+unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_hw_omap *oclk;
+
+	if (!hw) {
+		pr_warning("%s: hw is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	oclk = to_clk_hw_omap(hw);
+
+	WARN_ON(!oclk->fixed_div);
+
+	return parent_rate / oclk->fixed_div;
+}
+#endif
+
 /*
  * OMAP2+ specific clock functions
  */
@@ -61,7 +89,11 @@ static bool clkdm_control = true;
  * belong in the clock code and will be moved in the medium term to
  * module-dependent code.  No return value.
  */
+#ifdef CONFIG_COMMON_CLK
+static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
+#else
 static void _omap2_module_wait_ready(struct clk *clk)
+#endif
 {
 	void __iomem *companion_reg, *idlest_reg;
 	u8 other_bit, idlest_bit, idlest_val;
@@ -74,9 +106,12 @@ static void _omap2_module_wait_ready(struct clk *clk)
 	}
 
 	clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-
 	omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), idlest_val,
+#ifdef CONFIG_COMMON_CLK
+			     __clk_get_name(clk->hw.clk));
+#else
 			     __clk_get_name(clk));
+#endif
 }
 
 /* Public functions */
@@ -89,15 +124,25 @@ static void _omap2_module_wait_ready(struct clk *clk)
  * clockdomain pointer, and save it into the struct clk.  Intended to be
  * called during clk_register().  No return value.
  */
+#ifdef CONFIG_COMMON_CLK
+void omap2_init_clk_clkdm(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 void omap2_init_clk_clkdm(struct clk *clk)
 {
+#endif
 	struct clockdomain *clkdm;
 	const char *clk_name;
 
 	if (!clk->clkdm_name)
 		return;
 
+#ifdef CONFIG_COMMON_CLK
+	clk_name = __clk_get_name(hw->clk);
+#else
 	clk_name = __clk_get_name(clk);
+#endif
 
 	clkdm = clkdm_lookup(clk->clkdm_name);
 	if (clkdm) {
@@ -144,8 +189,12 @@ void __init omap2_clk_disable_clkdm_control(void)
  * associate this type of code with per-module data structures to
  * avoid this issue, and remove the casts.  No return value.
  */
-void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
-				   u8 *other_bit)
+#ifdef CONFIG_COMMON_CLK
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+#else
+void omap2_clk_dflt_find_companion(struct clk *clk,
+#endif
+			void __iomem **other_reg, u8 *other_bit)
 {
 	u32 r;
 
@@ -173,8 +222,12 @@ void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
  * register address ID (e.g., that CM_FCLKEN2 corresponds to
  * CM_IDLEST2).  This is not true for all modules.  No return value.
  */
-void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
-				u8 *idlest_bit, u8 *idlest_val)
+#ifdef CONFIG_COMMON_CLK
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+#else
+void omap2_clk_dflt_find_idlest(struct clk *clk,
+#endif
+		void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
 {
 	u32 r;
 
@@ -196,6 +249,133 @@ void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
 
 }
 
+#ifdef CONFIG_COMMON_CLK
+int omap2_dflt_clk_enable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk;
+	u32 v;
+	int ret = 0;
+
+	clk = to_clk_hw_omap(hw);
+
+	if (clkdm_control && clk->clkdm) {
+		ret = clkdm_clk_enable(clk->clkdm, hw->clk);
+		if (ret) {
+			WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
+					__func__, __clk_get_name(hw->clk),
+					clk->clkdm->name, ret);
+			return ret;
+		}
+	}
+
+	if (unlikely(clk->enable_reg == NULL)) {
+		pr_err("%s: %s missing enable_reg\n", __func__,
+				__clk_get_name(hw->clk));
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* FIXME should not have INVERT_ENABLE bit here */
+	v = __raw_readl(clk->enable_reg);
+	if (clk->flags & INVERT_ENABLE)
+		v &= ~(1 << clk->enable_bit);
+	else
+		v |= (1 << clk->enable_bit);
+	__raw_writel(v, clk->enable_reg);
+	v = __raw_readl(clk->enable_reg); /* OCP barrier */
+
+	if (clk->ops && clk->ops->find_idlest)
+		_omap2_module_wait_ready(clk);
+
+	return 0;
+
+err:
+	if (clkdm_control && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
+	return ret;
+}
+
+void omap2_dflt_clk_disable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk;
+	u32 v;
+
+	clk = to_clk_hw_omap(hw);
+	if (!clk->enable_reg) {
+		/*
+		 * 'independent' here refers to a clock which is not
+		 * controlled by its parent.
+		 */
+		pr_err("%s: independent clock %s has no enable_reg\n",
+				__func__, __clk_get_name(hw->clk));
+		return;
+	}
+
+	v = __raw_readl(clk->enable_reg);
+	if (clk->flags & INVERT_ENABLE)
+		v |= (1 << clk->enable_bit);
+	else
+		v &= ~(1 << clk->enable_bit);
+	__raw_writel(v, clk->enable_reg);
+	/* No OCP barrier needed here since it is a disable operation */
+
+	if (clkdm_control && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 regval32, v;
+
+	v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
+
+	regval32 = __raw_readl(clk->enable_reg);
+	if ((regval32 & (1 << clk->enable_bit)) == v)
+		return 0;
+
+	omap2_dflt_clk_enable(hw);
+
+	return 1;
+}
+
+int __initdata mpurate;
+
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init omap_clk_setup(char *str)
+{
+	get_option(&str, &mpurate);
+
+	if (!mpurate)
+		return 1;
+
+	if (mpurate < 1000)
+		mpurate *= 1000000;
+
+	return 1;
+}
+__setup("mpurate=", omap_clk_setup);
+
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
+};
+
+const struct clk_hw_omap_ops clkhwops_iclk_wait = {
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
+};
+
+const struct clk_hw_omap_ops clkhwops_wait = {
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
+};
+#else
 int omap2_dflt_clk_enable(struct clk *clk)
 {
 	u32 v;
@@ -446,6 +626,8 @@ void omap2_clk_disable_unused(struct clk *clk)
 }
 #endif
 
+#endif /* CONFIG_COMMON_CLK */
+
 /**
  * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
  * @mpurate_ck_name: clk name of the clock to change rate
@@ -476,13 +658,15 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
 	r = clk_set_rate(mpurate_ck, mpurate);
 	if (IS_ERR_VALUE(r)) {
 		WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
-		     mpurate_ck->name, mpurate, r);
+		     mpurate_ck_name, mpurate, r);
 		clk_put(mpurate_ck);
 		return -EINVAL;
 	}
 
 	calibrate_delay();
+#ifndef CONFIG_COMMON_CLK
 	recalculate_root_clocks();
+#endif
 
 	clk_put(mpurate_ck);
 
@@ -530,8 +714,8 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 		(clk_get_rate(mpu_ck) / 1000000));
 }
 
+#ifndef CONFIG_COMMON_CLK
 /* Common data */
-
 struct clk_functions omap2_clk_functions = {
 	.clk_enable		= omap2_clk_enable,
 	.clk_disable		= omap2_clk_disable,
@@ -540,4 +724,4 @@ struct clk_functions omap2_clk_functions = {
 	.clk_set_parent		= omap2_clk_set_parent,
 	.clk_disable_unused	= omap2_clk_disable_unused,
 };
-
+#endif
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index a1bb23a..2219271 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -54,6 +54,26 @@ void omap2_clk_disable(struct clk *clk);
 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);
+#ifdef CONFIG_COMMON_CLK
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			unsigned long *parent_rate);
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate);
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate);
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+				unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, unsigned long target_rate,
+				unsigned long *parent_rate);
+#else
 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);
@@ -68,17 +88,32 @@ void omap4_dpllmx_allow_gatectrl(struct clk *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk *clk);
 long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
+#endif
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
 #else
 #define omap2_clk_disable_unused	NULL
 #endif
-
+#ifdef CONFIG_COMMON_CLK
+void omap2_init_clk_clkdm(struct clk_hw *clk);
+#else
 void omap2_init_clk_clkdm(struct clk *clk);
+#endif
 void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
+#ifdef CONFIG_COMMON_CLK
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk, unsigned long target_rate,
+				u32 *new_div);
+u8 omap2_init_clksel_parent(struct clk_hw *hw);
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+				unsigned long *parent_rate);
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate);
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
+#else
 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 				u32 *new_div);
 void omap2_init_clksel_parent(struct clk *clk);
@@ -86,13 +121,19 @@ unsigned long omap2_clksel_recalc(struct clk *clk);
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
+#endif
 
 /* 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);
 
+#ifdef CONFIG_COMMON_CLK
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
+#else
 u32 omap2_get_dpll_rate(struct clk *clk);
 void omap2_init_dpll_parent(struct clk *clk);
+#endif
 
 int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
 
@@ -121,12 +162,22 @@ static inline void omap4_clk_prepare_for_reboot(void)
 }
 #endif
 
+#ifdef CONFIG_COMMON_CLK
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, void __iomem **other_reg,
+				   u8 *other_bit);
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, void __iomem **idlest_reg,
+				u8 *idlest_bit, u8 *idlest_val);
+#else
 int omap2_dflt_clk_enable(struct clk *clk);
 void omap2_dflt_clk_disable(struct clk *clk);
 void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
 				   u8 *other_bit);
 void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
 				u8 *idlest_bit, u8 *idlest_val);
+#endif
 int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 			       const char *core_ck_name,
@@ -146,6 +197,13 @@ extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
 
+#ifdef CONFIG_COMMON_CLK
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+#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;
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index d390f40..d6b2d39 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -44,7 +44,11 @@
 /* Private functions */
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
+#ifdef CONFIG_COMMON_CLK
+static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
+#else
 static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
+#endif
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -58,7 +62,11 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
+#ifdef CONFIG_COMMON_CLK
+static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
+#else
 static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
+#endif
 {
 	const struct dpll_data *dd;
 	int i = 0;
@@ -66,7 +74,11 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
 	const char *clk_name;
 
 	dd = clk->dpll_data;
+#ifdef CONFIG_COMMON_CLK
+	clk_name = __clk_get_name(clk->hw.clk);
+#else
 	clk_name = __clk_get_name(clk);
+#endif
 
 	state <<= __ffs(dd->idlest_mask);
 
@@ -90,7 +102,11 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
 }
 
 /* From 3430 TRM ES2 4.7.6.2 */
+#ifdef CONFIG_COMMON_CLK
+static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
+#else
 static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
+#endif
 {
 	unsigned long fint;
 	u16 f = 0;
@@ -135,12 +151,20 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
  * locked successfully, return 0; if the DPLL did not lock in the time
  * allotted, or DPLL3 was passed in, return -EINVAL.
  */
+#ifdef CONFIG_COMMON_CLK
+static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
+#else
 static int _omap3_noncore_dpll_lock(struct clk *clk)
+#endif
 {
 	u8 ai;
 	int r;
 
+#ifdef CONFIG_COMMON_CLK
+	pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
+#else
 	pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk));
+#endif
 
 	ai = omap3_dpll_autoidle_read(clk);
 
@@ -170,7 +194,11 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
  * DPLL3 was passed in, or the DPLL does not support low-power bypass,
  * return -EINVAL.
  */
+#ifdef CONFIG_COMMON_CLK
+static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
+#else
 static int _omap3_noncore_dpll_bypass(struct clk *clk)
+#endif
 {
 	int r;
 	u8 ai;
@@ -179,7 +207,11 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
 		return -EINVAL;
 
 	pr_debug("clock: configuring DPLL %s for low-power bypass\n",
+#ifdef CONFIG_COMMON_CLK
+		 __clk_get_name(clk->hw.clk));
+#else
 		 __clk_get_name(clk));
+#endif
 
 	ai = omap3_dpll_autoidle_read(clk);
 
@@ -202,14 +234,22 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
  * code.  If DPLL3 was passed in, or the DPLL does not support
  * low-power stop, return -EINVAL; otherwise, return 0.
  */
+#ifdef CONFIG_COMMON_CLK
+static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
+#else
 static int _omap3_noncore_dpll_stop(struct clk *clk)
+#endif
 {
 	u8 ai;
 
 	if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
 		return -EINVAL;
 
+#ifdef CONFIG_COMMON_CLK
+	pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
+#else
 	pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk));
+#endif
 
 	ai = omap3_dpll_autoidle_read(clk);
 
@@ -233,11 +273,19 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
  * XXX This code is not needed for 3430/AM35xx; can it be optimized
  * out in non-multi-OMAP builds for those chips?
  */
+#ifdef CONFIG_COMMON_CLK
+static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
+#else
 static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
+#endif
 {
 	unsigned long fint, clkinp; /* watch out for overflow */
 
+#ifdef CONFIG_COMMON_CLK
+	clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+#else
 	clkinp = __clk_get_rate(__clk_get_parent(clk));
+#endif
 	fint = (clkinp / n) * m;
 
 	if (fint < 1000000000)
@@ -258,12 +306,20 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
  * XXX This code is not needed for 3430/AM35xx; can it be optimized
  * out in non-multi-OMAP builds for those chips?
  */
+#ifdef CONFIG_COMMON_CLK
+static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
+#else
 static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
+#endif
 {
 	unsigned long clkinp, sd; /* watch out for overflow */
 	int mod1, mod2;
 
+#ifdef CONFIG_COMMON_CLK
+	clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+#else
 	clkinp = __clk_get_rate(__clk_get_parent(clk));
+#endif
 
 	/*
 	 * target sigma-delta to near 250MHz
@@ -290,7 +346,11 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
  * Program the DPLL with the supplied M, N values, and wait for the DPLL to
  * lock..  Returns -EINVAL upon error, or 0 upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n, u16 freqsel)
+#else
 static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
+#endif
 {
 	struct dpll_data *dd = clk->dpll_data;
 	u8 dco, sd_div;
@@ -347,8 +407,14 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
  *
  * Recalculate and propagate the DPLL rate.
  */
+#ifdef CONFIG_COMMON_CLK
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 unsigned long omap3_dpll_recalc(struct clk *clk)
 {
+#endif
 	return omap2_get_dpll_rate(clk);
 }
 
@@ -368,8 +434,14 @@ unsigned long omap3_dpll_recalc(struct clk *clk)
  * support low-power stop, or if the DPLL took too long to enter
  * bypass or lock, return -EINVAL; otherwise, return 0.
  */
+#ifdef CONFIG_COMMON_CLK
+int omap3_noncore_dpll_enable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 int omap3_noncore_dpll_enable(struct clk *clk)
 {
+#endif
 	int r;
 	struct dpll_data *dd;
 	struct clk *parent;
@@ -378,15 +450,23 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 	if (!dd)
 		return -EINVAL;
 
+#ifdef CONFIG_COMMON_CLK
+	parent = __clk_get_parent(hw->clk);
+
+	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
+#else
 	parent = __clk_get_parent(clk);
 
 	if (__clk_get_rate(clk) == __clk_get_rate(dd->clk_bypass)) {
+#endif
 		WARN_ON(parent != dd->clk_bypass);
 		r = _omap3_noncore_dpll_bypass(clk);
 	} else {
 		WARN_ON(parent != dd->clk_ref);
 		r = _omap3_noncore_dpll_lock(clk);
 	}
+
+#ifndef CONFIG_COMMON_CLK
 	/*
 	 *FIXME: this is dubious - if clk->rate has changed, what about
 	 * propagating?
@@ -394,6 +474,7 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 	if (!r)
 		clk->rate = (clk->recalc) ? clk->recalc(clk) :
 			omap2_get_dpll_rate(clk);
+#endif
 
 	return r;
 }
@@ -405,8 +486,14 @@ int omap3_noncore_dpll_enable(struct clk *clk)
  * Instructs a non-CORE DPLL to enter low-power stop.  This function is
  * intended for use in struct clkops.  No return value.
  */
+#ifdef CONFIG_COMMON_CLK
+void omap3_noncore_dpll_disable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 void omap3_noncore_dpll_disable(struct clk *clk)
 {
+#endif
 	_omap3_noncore_dpll_stop(clk);
 }
 
@@ -424,6 +511,77 @@ void omap3_noncore_dpll_disable(struct clk *clk)
  * target rate if it hasn't been done already, then program and lock
  * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
  */
+#ifdef CONFIG_COMMON_CLK
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct clk *new_parent = NULL;
+	u16 freqsel = 0;
+	struct dpll_data *dd;
+	int ret;
+
+	if (!hw || !rate)
+		return -EINVAL;
+
+	dd = clk->dpll_data;
+	if (!dd)
+		return -EINVAL;
+
+	__clk_prepare(dd->clk_bypass);
+	clk_enable(dd->clk_bypass);
+	__clk_prepare(dd->clk_ref);
+	clk_enable(dd->clk_ref);
+
+	if (__clk_get_rate(dd->clk_bypass) == rate &&
+			(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+		pr_debug("%s: %s: set rate: entering bypass.\n",
+				__func__, __clk_get_name(hw->clk));
+
+		ret = _omap3_noncore_dpll_bypass(clk);
+		if (!ret)
+			new_parent = dd->clk_bypass;
+	} else {
+		if (dd->last_rounded_rate != rate)
+			rate = __clk_round_rate(hw->clk, rate);
+
+		if (dd->last_rounded_rate == 0)
+			return -EINVAL;
+
+		/* No freqsel on OMAP4 and OMAP3630 */
+		if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
+			freqsel = _omap3_dpll_compute_freqsel(clk,
+						dd->last_rounded_n);
+			if (!freqsel)
+				WARN_ON(1);
+		}
+
+		pr_debug("%s: %s: set rate: locking rate to %lu.\n",
+			__func__, __clk_get_name(hw->clk), rate);
+
+		ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
+						dd->last_rounded_n, freqsel);
+		if (!ret)
+			new_parent = dd->clk_ref;
+	}
+	/*
+	* FIXME - this is all wrong.  common code handles reparenting and
+	* migrating prepare/enable counts.  dplls should be a multiplexer
+	* clock and this should be a set_parent operation so that all of that
+	* stuff is inherited for free
+	*/
+
+	if (!ret)
+		__clk_reparent(hw->clk, new_parent);
+
+	clk_disable(dd->clk_ref);
+	__clk_unprepare(dd->clk_ref);
+	clk_disable(dd->clk_bypass);
+	__clk_unprepare(dd->clk_bypass);
+
+	return 0;
+}
+#else
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk *new_parent = NULL;
@@ -500,6 +658,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 
 	return 0;
 }
+#endif
 
 /* DPLL autoidle read/set code */
 
@@ -511,7 +670,11 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
  * -EINVAL if passed a null pointer or if the struct clk does not
  * appear to refer to a DPLL.
  */
+#ifdef CONFIG_COMMON_CLK
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
+#else
 u32 omap3_dpll_autoidle_read(struct clk *clk)
+#endif
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -540,7 +703,11 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
  * OMAP3430.  The DPLL will enter low-power stop when its downstream
  * clocks are gated.  No return value.
  */
+#ifdef CONFIG_COMMON_CLK
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
+#else
 void omap3_dpll_allow_idle(struct clk *clk)
+#endif
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -551,8 +718,10 @@ void omap3_dpll_allow_idle(struct clk *clk)
 	dd = clk->dpll_data;
 
 	if (!dd->autoidle_reg) {
+#ifndef CONFIG_COMMON_CLK
 		pr_debug("clock: DPLL %s: autoidle not supported\n",
 			__clk_get_name(clk));
+#endif
 		return;
 	}
 
@@ -574,7 +743,11 @@ void omap3_dpll_allow_idle(struct clk *clk)
  *
  * Disable DPLL automatic idle control.  No return value.
  */
+#ifdef CONFIG_COMMON_CLK
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
+#else
 void omap3_dpll_deny_idle(struct clk *clk)
+#endif
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -585,8 +758,10 @@ void omap3_dpll_deny_idle(struct clk *clk)
 	dd = clk->dpll_data;
 
 	if (!dd->autoidle_reg) {
+#ifndef CONFIG_COMMON_CLK
 		pr_debug("clock: DPLL %s: autoidle not supported\n",
 			__clk_get_name(clk));
+#endif
 		return;
 	}
 
@@ -606,6 +781,26 @@ void omap3_dpll_deny_idle(struct clk *clk)
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
+#ifdef CONFIG_COMMON_CLK
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate)
+{
+	const struct dpll_data *dd;
+	unsigned long rate;
+	u32 v;
+	struct clk_hw_omap *pclk = NULL;
+	struct clk *parent;
+
+	/* Walk up the parents of clk, looking for a DPLL */
+	do {
+		do {
+			parent = __clk_get_parent(hw->clk);
+			hw = __clk_get_hw(parent);
+		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+		if (!hw)
+			break;
+		pclk = to_clk_hw_omap(hw);
+	} while (pclk && !pclk->dpll_data);
+#else
 unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 {
 	const struct dpll_data *dd;
@@ -619,6 +814,8 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 	while (pclk && !pclk->dpll_data)
 		pclk = __clk_get_parent(pclk);
 
+	parent_rate = __clk_get_rate(__clk_get_parent(clk));
+#endif
 	/* clk does not have a DPLL as a parent? */
 	WARN_ON(!pclk);
 
@@ -626,7 +823,6 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 
 	WARN_ON(!dd->enable_mask);
 
-	parent_rate = __clk_get_rate(__clk_get_parent(clk));
 	v = __raw_readl(dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 	if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 9c6a296..fbf94d2 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -23,7 +23,11 @@
 #include "cm-regbits-44xx.h"
 
 /* Supported only on OMAP4 */
+#ifdef CONFIG_COMMON_CLK
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
+#else
 int omap4_dpllmx_gatectrl_read(struct clk *clk)
+#endif
 {
 	u32 v;
 	u32 mask;
@@ -42,7 +46,11 @@ int omap4_dpllmx_gatectrl_read(struct clk *clk)
 	return v;
 }
 
+#ifdef CONFIG_COMMON_CLK
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
+#else
 void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+#endif
 {
 	u32 v;
 	u32 mask;
@@ -60,7 +68,11 @@ void omap4_dpllmx_allow_gatectrl(struct clk *clk)
 	__raw_writel(v, clk->clksel_reg);
 }
 
+#ifdef CONFIG_COMMON_CLK
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
+#else
 void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+#endif
 {
 	u32 v;
 	u32 mask;
@@ -78,10 +90,17 @@ void omap4_dpllmx_deny_gatectrl(struct clk *clk)
 	__raw_writel(v, clk->clksel_reg);
 }
 
+#ifdef CONFIG_COMMON_CLK
+const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
+	.allow_idle	= omap4_dpllmx_allow_gatectrl,
+	.deny_idle      = omap4_dpllmx_deny_gatectrl,
+};
+#else
 const struct clkops clkops_omap4_dpllmx_ops = {
 	.allow_idle	= omap4_dpllmx_allow_gatectrl,
 	.deny_idle	= omap4_dpllmx_deny_gatectrl,
 };
+#endif
 
 /**
  * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
@@ -92,8 +111,15 @@ const struct clkops clkops_omap4_dpllmx_ops = {
  * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
  * upon success, or 0 upon error.
  */
+#ifdef CONFIG_COMMON_CLK
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+			unsigned long parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
 {
+#endif
 	u32 v;
 	unsigned long rate;
 	struct dpll_data *dd;
@@ -125,8 +151,15 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
  * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
  * ~0 if an error occurred in omap2_dpll_round_rate().
  */
+#ifdef CONFIG_COMMON_CLK
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			unsigned long *parent_rate)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+#else
 long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
 {
+#endif
 	u32 v;
 	struct dpll_data *dd;
 	long r;
@@ -142,7 +175,11 @@ long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
 	if (v)
 		target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
 
+#ifdef CONFIG_COMMON_CLK
+	r = omap2_dpll_round_rate(hw, target_rate, NULL);
+#else
 	r = omap2_dpll_round_rate(clk, target_rate);
+#endif
 	if (r == ~0)
 		return r;
 
-- 
1.7.1




More information about the linux-arm-kernel mailing list