ARM: OMAP4: clock: Convert to common clk

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@ti.com>
[paul@pwsan.com: created new omap2_clksel_find_parent_index() rather than
 modifying omap2_init_clksel_parent(); moved clkhwops_iclk_wait to
 clkt_iclk.c to fix OMAP4-only builds; added clk-provider.h include to clock.h
 to try to fix some 3430-builds]
[mturquette@ti.com: squash patch for omap2_clkops_{en,dis}able_clkdm;
 omap2_dflt_clk_is_enabled should not enable clocks]
Signed-off-by: Mike Turquette <mturquette@ti.com>
[paul@pwsan.com: fix compiler warning; update to apply; added kerneldoc on
 non-trivial new functions; added the dpll3xxx clockdomain modifications]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index eacf51f..f72dedb 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -29,6 +29,7 @@
 #include <linux/clkdev.h>
 
 #include "soc.h"
+#include "clockdomain.h"
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
@@ -42,7 +43,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;
@@ -56,7 +61,11 @@
 }
 
 /* _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;
@@ -64,7 +73,11 @@
 	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);
 
@@ -88,7 +101,11 @@
 }
 
 /* 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;
@@ -133,14 +150,22 @@
  * 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
 {
 	const struct dpll_data *dd;
 	u8 ai;
 	u8 state = 1;
 	int r = 0;
 
+#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
 
 	dd = clk->dpll_data;
 	state <<= __ffs(dd->idlest_mask);
@@ -178,7 +203,11 @@
  * 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;
@@ -187,7 +216,11 @@
 		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);
 
@@ -210,14 +243,22 @@
  * 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);
 
@@ -241,11 +282,19 @@
  * 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)
@@ -266,12 +315,20 @@
  * 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
@@ -298,7 +355,12 @@
  * 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;
@@ -355,8 +417,14 @@
  *
  * 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);
 }
 
@@ -376,8 +444,14 @@
  * 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;
@@ -386,15 +460,34 @@
 	if (!dd)
 		return -EINVAL;
 
+#ifdef CONFIG_COMMON_CLK
+	if (clk->clkdm) {
+		r = clkdm_clk_enable(clk->clkdm, hw->clk);
+		if (r) {
+			WARN(1,
+			     "%s: could not enable %s's clockdomain %s: %d\n",
+			     __func__, __clk_get_name(hw->clk),
+			     clk->clkdm->name, r);
+			return r;
+		}
+	}
+
+	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?
@@ -402,6 +495,7 @@
 	if (!r)
 		clk->rate = (clk->recalc) ? clk->recalc(clk) :
 			omap2_get_dpll_rate(clk);
+#endif
 
 	return r;
 }
@@ -413,9 +507,21 @@
  * 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);
+
+	_omap3_noncore_dpll_stop(clk);
+	if (clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
+#else
 void omap3_noncore_dpll_disable(struct clk *clk)
 {
 	_omap3_noncore_dpll_stop(clk);
+	if (clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, clk);
+#endif
 }
 
 
@@ -432,6 +538,77 @@
  * 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;
@@ -509,6 +686,7 @@
 
 	return 0;
 }
+#endif
 
 /* DPLL autoidle read/set code */
 
@@ -520,7 +698,11 @@
  * -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;
@@ -549,7 +731,11 @@
  * 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;
@@ -560,8 +746,10 @@
 	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;
 	}
 
@@ -583,7 +771,11 @@
  *
  * 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;
@@ -594,8 +786,10 @@
 	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;
 	}
 
@@ -615,6 +809,27 @@
  * 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;
@@ -628,6 +843,8 @@
 	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?  error in the clock data */
 	if (!pclk) {
 		WARN_ON(1);
@@ -638,7 +855,6 @@
 
 	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))
@@ -649,7 +865,12 @@
 }
 
 /* OMAP3/4 non-CORE DPLL clkops */
-
+#ifdef CONFIG_COMMON_CLK
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
+};
+#else
 const struct clkops clkops_omap3_noncore_dpll_ops = {
 	.enable		= omap3_noncore_dpll_enable,
 	.disable	= omap3_noncore_dpll_disable,
@@ -661,3 +882,4 @@
 	.allow_idle	= omap3_dpll_allow_idle,
 	.deny_idle	= omap3_dpll_deny_idle,
 };
+#endif