Kaynağa Gözat

Merge tag 'for-v3.17/omap-clock-a' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.17/soc

An OMAP clock cleanup series for 3.17 from Tero Kristo.
This is in preparation for moving this code into drivers/clk/ti.

Basic build, boot, and PM test logs are here:

http://www.pwsan.com/omap/testlogs/clock-a-v3.17/20140717034329/
Tony Lindgren 11 yıl önce
ebeveyn
işleme
3db53918e3

+ 45 - 53
arch/arm/mach-omap2/clkt_dpll.c

@@ -21,10 +21,7 @@
 
 #include <asm/div64.h>
 
-#include "soc.h"
 #include "clock.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
 
 /* DPLL rate rounding: minimum DPLL multiplier, divider values */
 #define DPLL_MIN_MULTIPLIER		2
@@ -44,20 +41,12 @@
 #define DPLL_ROUNDING_VAL		((DPLL_SCALE_BASE / 2) * \
 					 (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
-/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
-#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
-#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
-#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
-
 /*
  * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
  * From device data manual section 4.3 "DPLL and DLL Specifications".
  */
 #define OMAP3PLUS_DPLL_FINT_JTYPE_MIN	500000
 #define OMAP3PLUS_DPLL_FINT_JTYPE_MAX	2500000
-#define OMAP3PLUS_DPLL_FINT_MIN		32000
-#define OMAP3PLUS_DPLL_FINT_MAX		52000000
 
 /* _dpll_test_fint() return codes */
 #define DPLL_FINT_UNDERFLOW		-1
@@ -87,33 +76,31 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
 	/* DPLL divider must result in a valid jitter correction val */
 	fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
 
-	if (cpu_is_omap24xx()) {
-		/* Should not be called for OMAP2, so warn if it is called */
-		WARN(1, "No fint limits available for OMAP2!\n");
-		return DPLL_FINT_INVALID;
-	} else if (cpu_is_omap3430()) {
-		fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
-		fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
-	} else if (dd->flags & DPLL_J_TYPE) {
+	if (dd->flags & DPLL_J_TYPE) {
 		fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
 		fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
 	} else {
-		fint_min = OMAP3PLUS_DPLL_FINT_MIN;
-		fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+		fint_min = ti_clk_features.fint_min;
+		fint_max = ti_clk_features.fint_max;
 	}
 
-	if (fint < fint_min) {
+	if (!fint_min || !fint_max) {
+		WARN(1, "No fint limits available!\n");
+		return DPLL_FINT_INVALID;
+	}
+
+	if (fint < ti_clk_features.fint_min) {
 		pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
 			 n);
 		dd->max_divider = n;
 		ret = DPLL_FINT_UNDERFLOW;
-	} else if (fint > fint_max) {
+	} else if (fint > ti_clk_features.fint_max) {
 		pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
 			 n);
 		dd->min_divider = n;
 		ret = DPLL_FINT_INVALID;
-	} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
-		   fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+	} else if (fint > ti_clk_features.fint_band1_max &&
+		   fint < ti_clk_features.fint_band2_min) {
 		pr_debug("rejecting n=%d due to Fint failure\n", n);
 		ret = DPLL_FINT_INVALID;
 	}
@@ -185,6 +172,34 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
 	return r;
 }
 
+/**
+ * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
+ * @v: bitfield value of the DPLL enable
+ *
+ * Checks given DPLL enable bitfield to see whether the DPLL is in bypass
+ * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise.
+ */
+static int _omap2_dpll_is_in_bypass(u32 v)
+{
+	u8 mask, val;
+
+	mask = ti_clk_features.dpll_bypass_vals;
+
+	/*
+	 * Each set bit in the mask corresponds to a bypass value equal
+	 * to the bitshift. Go through each set-bit in the mask and
+	 * compare against the given register value.
+	 */
+	while (mask) {
+		val = __ffs(mask);
+		mask ^= (1 << val);
+		if (v == val)
+			return 1;
+	}
+
+	return 0;
+}
+
 /* Public functions */
 u8 omap2_init_dpll_parent(struct clk_hw *hw)
 {
@@ -201,20 +216,9 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
 	v >>= __ffs(dd->enable_mask);
 
 	/* 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)
-			return 1;
-	} else if (cpu_is_omap34xx()) {
-		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-			return 1;
-	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
-		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-			return 1;
-	}
+	if (_omap2_dpll_is_in_bypass(v))
+		return 1;
+
 	return 0;
 }
 
@@ -247,20 +251,8 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
-	if (cpu_is_omap24xx()) {
-		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	} else if (cpu_is_omap34xx()) {
-		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
-		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
-		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-			return __clk_get_rate(dd->clk_bypass);
-	}
+	if (_omap2_dpll_is_in_bypass(v))
+		return __clk_get_rate(dd->clk_bypass);
 
 	v = omap2_clk_readl(clk, dd->mult_div1_reg);
 	dpll_mult = v & dd->mult_mask;

+ 4 - 4
arch/arm/mach-omap2/clkt_iclk.c

@@ -14,11 +14,11 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 
-
 #include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
+
+/* Register offsets */
+#define CM_AUTOIDLE			0x30
+#define CM_ICLKEN			0x10
 
 /* Private functions */
 

+ 69 - 7
arch/arm/mach-omap2/clock.c

@@ -46,6 +46,24 @@
 
 u16 cpu_mask;
 
+/*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features ti_clk_features;
+
+/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
+#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_MIN		32000
+#define OMAP3PLUS_DPLL_FINT_MAX		52000000
+
 /*
  * clkdm_control: if true, then when a clock is enabled in the
  * hardware, its clockdomain will first be enabled; and when a clock
@@ -287,13 +305,7 @@ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
 	 * 34xx reverses this, just to keep us on our toes
 	 * AM35xx uses both, depending on the module.
 	 */
-	if (cpu_is_omap24xx())
-		*idlest_val = OMAP24XX_CM_IDLEST_VAL;
-	else if (cpu_is_omap34xx())
-		*idlest_val = OMAP34XX_CM_IDLEST_VAL;
-	else
-		BUG();
-
+	*idlest_val = ti_clk_features.cm_idlest_val;
 }
 
 /**
@@ -731,3 +743,53 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 		(clk_get_rate(core_ck) / 1000000),
 		(clk_get_rate(mpu_ck) / 1000000));
 }
+
+/**
+ * ti_clk_init_features - init clock features struct for the SoC
+ *
+ * Initializes the clock features struct based on the SoC type.
+ */
+void __init ti_clk_init_features(void)
+{
+	/* Fint setup for DPLLs */
+	if (cpu_is_omap3430()) {
+		ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+		ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+		ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
+		ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
+	} else {
+		ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+		ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+	}
+
+	/* Bypass value setup for DPLLs */
+	if (cpu_is_omap24xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP2XXX_EN_DPLL_FRBYPASS);
+	} else if (cpu_is_omap34xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP3XXX_EN_DPLL_FRBYPASS);
+	} else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
+		   soc_is_omap54xx() || soc_is_dra7xx()) {
+		ti_clk_features.dpll_bypass_vals |=
+			(1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
+			(1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
+			(1 << OMAP4XXX_EN_DPLL_MNBYPASS);
+	}
+
+	/* Jitter correction only available on OMAP343X */
+	if (cpu_is_omap343x())
+		ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
+
+	/* Idlest value for interface clocks.
+	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+	 * 34xx reverses this, just to keep us on our toes
+	 * AM35xx uses both, depending on the module.
+	 */
+	if (cpu_is_omap24xx())
+		ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
+	else if (cpu_is_omap34xx())
+		ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}

+ 19 - 25
arch/arm/mach-omap2/clock.h

@@ -101,31 +101,6 @@ struct clockdomain;
 	};							\
 	DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
 
-#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name,		\
-				_parent_ptr, _flags,		\
-				_clksel_reg, _clksel_mask)	\
-	static const struct clksel _name##_div[] = {		\
-		{						\
-			.parent = _parent_ptr,			\
-			.rates = div31_1to31_rates		\
-		},						\
-		{ .parent = NULL },				\
-	};							\
-	static struct clk _name;				\
-	static const char *_name##_parent_names[] = {		\
-		_parent_name,					\
-	};							\
-	static struct clk_hw_omap _name##_hw = {		\
-		.hw = {						\
-			.clk = &_name,				\
-		},						\
-		.clksel		= _name##_div,			\
-		.clksel_reg	= _clksel_reg,			\
-		.clksel_mask	= _clksel_mask,			\
-		.ops		= &clkhwops_omap4_dpllmx,	\
-	};							\
-	DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
-
 /* struct clksel_rate.flags possibilities */
 #define RATE_IN_242X		(1 << 0)
 #define RATE_IN_243X		(1 << 1)
@@ -248,6 +223,23 @@ void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
 
 extern u16 cpu_mask;
 
+/*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features {
+	u32 flags;
+	long fint_min;
+	long fint_max;
+	long fint_band1_max;
+	long fint_band2_min;
+	u8 dpll_bypass_vals;
+	u8 cm_idlest_val;
+};
+
+#define TI_CLK_DPLL_HAS_FREQSEL		(1 << 0)
+
+extern struct ti_clk_features ti_clk_features;
+
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_dummy;
 extern const struct clkops clkops_omap2_dflt;
@@ -286,4 +278,6 @@ extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
 extern void omap_clocks_register(struct omap_clk *oclks, int cnt);
+
+void __init ti_clk_init_features(void);
 #endif

+ 2 - 5
arch/arm/mach-omap2/dpll3xxx.c

@@ -28,11 +28,8 @@
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
 
-#include "soc.h"
 #include "clockdomain.h"
 #include "clock.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 #define DPLL_AUTOIDLE_DISABLE			0x0
@@ -310,7 +307,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 	 * Set jitter correction. Jitter correction applicable for OMAP343X
 	 * only since freqsel field is no longer present on other devices.
 	 */
-	if (cpu_is_omap343x()) {
+	if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
 		v = omap2_clk_readl(clk, dd->control_reg);
 		v &= ~dd->freqsel_mask;
 		v |= freqsel << __ffs(dd->freqsel_mask);
@@ -512,7 +509,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 			return -EINVAL;
 
 		/* Freqsel is available only on OMAP343X devices */
-		if (cpu_is_omap343x()) {
+		if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			WARN_ON(!freqsel);

+ 13 - 6
arch/arm/mach-omap2/dpll44xx.c

@@ -15,10 +15,7 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 
-#include "soc.h"
 #include "clock.h"
-#include "clock44xx.h"
-#include "cm-regbits-44xx.h"
 
 /*
  * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
@@ -29,13 +26,23 @@
 #define OMAP4_DPLL_LP_FINT_MAX	1000000
 #define OMAP4_DPLL_LP_FOUT_MAX	100000000
 
+/*
+ * Bitfield declarations
+ */
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK		(1 << 8)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK		(1 << 10)
+#define OMAP4430_DPLL_REGM4XEN_MASK			(1 << 11)
+
+/* Static rate multiplier for OMAP4 REGM4XEN clocks */
+#define OMAP4430_REGM4XEN_MULT				4
+
 /* Supported only on OMAP4 */
 int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
 {
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return -EINVAL;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -54,7 +61,7 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -72,7 +79,7 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
 	u32 v;
 	u32 mask;
 
-	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+	if (!clk || !clk->clksel_reg)
 		return;
 
 	mask = clk->flags & CLOCK_CLKOUTX2 ?

+ 2 - 0
arch/arm/mach-omap2/io.c

@@ -728,6 +728,8 @@ int __init omap_clk_init(void)
 	if (!omap_clk_soc_init)
 		return 0;
 
+	ti_clk_init_features();
+
 	ret = of_prcm_init();
 	if (!ret)
 		ret = omap_clk_soc_init();