Skip to contentSkip to conversation

Series short description

PATCH Superseded Paul Walmsley 2 participants 26 messages Dec 23, 2008 – Jan 5, 2009

Subsystems (6)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Paul Walmsley

author maintainer
#0 lore raw

cover Series short description

OMAP clock: bug fixes, cleanup, optimization

Hello,

this 22-patch series updates the OMAP1/2/3 clock code. Highlights:

- Rate recalculation functions are now no longer responsible for rate propagation - now handled by plat-omap/clock.c (patches 2, 3,
4)

- Parent-to-child traversals of the clock tree are now much faster - these occur during rate propagation and clock notifiers (patch 5)

- Many superfluous clock flags have been dropped (patches 6, 7, 8, 9)

- struct clk has been streamlined by removing unused members and rearranging the structure to reduce padding (patches 10, 11)

- MPU barriers have been either removed or converted to OCP barriers (patches 12, 13, 14)

- clk_get_usecount() has been dropped (patch 15)

- omap2_clk_enable() has been overhauled: two bugs were fixed and the function body itself is now understandable (patches 16, 17, 18, 19, 20)

- Unnecessary custom clocks in smartreflex.c have been removed (patch 22)

- Miscellaneous bug fixes (patches 1, 21)

Compile-tested on OMAP1. Boot-tested on N800 and 3430SDP GP ES2.1.

- Paul

---

size:
text data bss dec hex filename

3582958  190280  108824 3882062  3b3c4e vmlinux.3430sdp.orig
3582501  190928  108824 3882253  3b3d0d vmlinux.3430sdp.patched

text data bss dec hex filename

3167206  152232   86176 3405614  33f72e vmlinux.n800.orig
3167453  152784   86176 3406413  33fa4d vmlinux.n800.patched

diffstat:

 arch/arm/mach-omap1/clock.c             |   87 +++++++----
 arch/arm/mach-omap1/clock.h             |   64 ++++----
 arch/arm/mach-omap2/clock.c             |  151 ++++++++++---------
 arch/arm/mach-omap2/clock.h             |    8 +
 arch/arm/mach-omap2/clock24xx.c         |  125 ++++++++++------
 arch/arm/mach-omap2/clock24xx.h         |   89 ++++-------
 arch/arm/mach-omap2/clock34xx.c         |   47 +++---
 arch/arm/mach-omap2/clock34xx.h         |  228 +++++++++++------------------
 arch/arm/mach-omap2/pm-debug.c          |    2 
 arch/arm/mach-omap2/pm24xx.c            |    2 
 arch/arm/mach-omap2/smartreflex.c       |   89 ++---------
 arch/arm/plat-omap/clock.c              |  245 +++++++++++++++++++++++++------
 arch/arm/plat-omap/include/mach/clock.h |   73 ++++++---
 13 files changed, 663 insertions(+), 547 deletions(-)
author maintainer
#1 lore raw

PATCH 1/22 OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init()

Use the standard clk_set_rate() function in omap2_clk_arch_init() rather than omap2_select_table_rate() -- this will ensure that clock rates are recalculated and propagated correctly after those operations are consolidated into clk_set_rate().

---
 arch/arm/mach-omap2/clock24xx.c |    2 +-
 arch/arm/mach-omap2/clock34xx.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/clock24xx.c +1 -1
index ff14d12..8567de2 100644
@@ -501,7 +501,7 @@ static int __init omap2_clk_arch_init(void)
 	if (!mpurate)
 		return -EINVAL;
 
-	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+	if (clk_set_rate(&virt_prcm_set, mpurate))
 		printk(KERN_ERR "Could not find matching MPU rate\n");
 
 	recalculate_root_clocks();
arch/arm/mach-omap2/clock34xx.c +1 -1
index 2c655be..738a029 100644
@@ -665,7 +665,7 @@ static int __init omap2_clk_arch_init(void)
 
 	/* REVISIT: not yet ready for 343x */
 #if 0
-	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+	if (clk_set_rate(&virt_prcm_set, mpurate))
 		printk(KERN_ERR "Could not find matching MPU rate\n");
 #endif
 
author maintainer
#2 lore raw

PATCH 2/22 OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c

In reply to Paul Walmsley

Previously the individual clock recalculation functions handled their own rate recalculation. This can be handled in the clk_set_rate(), clk_set_parent(), and recalculate_root_clocks() functions in plat-omap/clock.c. Removes duplicate code and clarifies the role of the recalc functions.

---
 arch/arm/mach-omap1/clock.c     |   14 --------------
 arch/arm/mach-omap2/clock.c     |   12 ------------
 arch/arm/mach-omap2/clock24xx.c |    6 ------
 arch/arm/mach-omap2/clock34xx.c |    9 ---------
 arch/arm/plat-omap/clock.c      |   34 +++++++++++++++++++++++++++-------
 5 files changed, 27 insertions(+), 48 deletions(-)
arch/arm/mach-omap1/clock.c +0 -14
index 4d0c444..ae2b304 100644
@@ -225,9 +225,6 @@ static void omap1_ckctl_recalc(struct clk * clk)
 	if (unlikely(clk->rate == clk->parent->rate / dsor))
 		return; /* No change, quick exit */
 	clk->rate = clk->parent->rate / dsor;
-
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
 }
 
 static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
@@ -248,9 +245,6 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
 	if (unlikely(clk->rate == clk->parent->rate / dsor))
 		return; /* No change, quick exit */
 	clk->rate = clk->parent->rate / dsor;
-
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
 }
 
 /* MPU virtual clock functions */
@@ -314,9 +308,6 @@ static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
 		ret = 0;
 	}
 
-	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-		propagate_rate(clk);
-
 	return ret;
 }
 
@@ -423,8 +414,6 @@ static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)
 	omap_writel(l, MOD_CONF_CTRL_1);
 
 	clk->rate = p_rate / (div + 1);
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
 
 	return 0;
 }
@@ -583,9 +572,6 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
 		ret = 0;
 	}
 
-	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-		propagate_rate(clk);
-
 	return ret;
 }
 
arch/arm/mach-omap2/clock.c +0 -12
index 8a064b3..13db3d5 100644
@@ -302,9 +302,6 @@ void omap2_fixed_divisor_recalc(struct clk *clk)
 	WARN_ON(!clk->fixed_div);
 
 	clk->rate = clk->parent->rate / clk->fixed_div;
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
 }
 
 /**
@@ -506,9 +503,6 @@ void omap2_clksel_recalc(struct clk *clk)
 	clk->rate = clk->parent->rate / div;
 
 	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
 }
 
 /**
@@ -779,9 +773,6 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
 	if (clk->set_rate != NULL)
 		ret = clk->set_rate(clk, rate);
 
-	if (ret == 0 && (clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
-
 	return ret;
 }
 
@@ -863,9 +854,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
 		 clk->name, clk->parent->name, clk->rate);
 
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
-
 	return 0;
 }
 
arch/arm/mach-omap2/clock24xx.c +0 -6
index 8567de2..9e1328f 100644
@@ -178,8 +178,6 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 static void omap2_dpllcore_recalc(struct clk *clk)
 {
 	clk->rate = omap2xxx_clk_get_core_rate(clk);
-
-	propagate_rate(clk);
 }
 
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
@@ -250,7 +248,6 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
 		omap2xxx_sdrc_reprogram(done_rate, 0);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
 	ret = 0;
 
 dpll_exit:
@@ -379,7 +376,6 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
 		local_irq_restore(flags);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
 
 	return 0;
 }
@@ -469,13 +465,11 @@ static u32 omap2_get_sysclkdiv(void)
 static void omap2_osc_clk_recalc(struct clk *clk)
 {
 	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
-	propagate_rate(clk);
 }
 
 static void omap2_sys_clk_recalc(struct clk *clk)
 {
 	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
-	propagate_rate(clk);
 }
 
 /*
arch/arm/mach-omap2/clock34xx.c +0 -9
index 738a029..22cbcce 100644
@@ -54,8 +54,6 @@
 static void omap3_dpll_recalc(struct clk *clk)
 {
 	clk->rate = omap2_get_dpll_rate(clk);
-
-	propagate_rate(clk);
 }
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -429,8 +427,6 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 
 	}
 
-	omap3_dpll_recalc(clk);
-
 	return 0;
 }
 
@@ -493,8 +489,6 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 				  sp->actim_ctrlb, new_div);
 	local_irq_enable();
 
-	omap2_clksel_recalc(clk);
-
 	return 0;
 }
 
@@ -612,9 +606,6 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
 		clk->rate = clk->parent->rate;
 	else
 		clk->rate = clk->parent->rate * 2;
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
 }
 
 /* Common clock code */
arch/arm/plat-omap/clock.c +27 -7
index d13acd2..9f458cb 100644
@@ -183,8 +183,16 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_rate)
+
+	if (arch_clock->clk_set_rate) {
 		ret = arch_clock->clk_set_rate(clk, rate);
+		if (ret == 0) {
+			(*clk->recalc)(clk);
+			if (clk->flags & RATE_PROPAGATES)
+				propagate_rate(clk);
+		}
+	}
+
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -200,8 +208,16 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_parent)
-		ret =  arch_clock->clk_set_parent(clk, parent);
+
+	if (arch_clock->clk_set_parent) {
+		ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0) {
+			(*clk->recalc)(clk);
+			if (clk->flags & RATE_PROPAGATES)
+				propagate_rate(clk);
+		}
+	}
+
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -256,8 +272,6 @@ void followparent_recalc(struct clk *clk)
 		return;
 
 	clk->rate = clk->parent->rate;
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
 }
 
 /* Propagate rate to children */
@@ -271,8 +285,11 @@ void propagate_rate(struct clk * tclk)
 	list_for_each_entry(clkp, &clocks, node) {
 		if (likely(clkp->parent != tclk))
 			continue;
-		if (likely((u32)clkp->recalc))
+		if (likely((u32)clkp->recalc)) {
 			clkp->recalc(clkp);
+			if (clkp->flags & RATE_PROPAGATES)
+				propagate_rate(clkp);
+		}
 	}
 }
 
@@ -288,8 +305,11 @@ void recalculate_root_clocks(void)
 	struct clk *clkp;
 
 	list_for_each_entry(clkp, &clocks, node) {
-		if (unlikely(!clkp->parent) && likely((u32)clkp->recalc))
+		if (unlikely(!clkp->parent) && likely((u32)clkp->recalc)) {
 			clkp->recalc(clkp);
+			if (clkp->flags & RATE_PROPAGATES)
+				propagate_rate(clkp);
+		}
 	}
 }
 
author maintainer
#3 lore raw

PATCH 3/22 OMAP2/3 clock: drop recalc function pointers from fixed rate clocks

In reply to Paul Walmsley

Now that rate recalculation and rate propagation are two separate operations, drop recalc function pointers from all fixed rate clocks. Their rates are fixed, so there's no need to recalculate.

---
 arch/arm/mach-omap2/clock24xx.h |    4 ----
 arch/arm/mach-omap2/clock34xx.h |   10 ----------
 arch/arm/plat-omap/clock.c      |   18 ++++++++++--------
 3 files changed, 10 insertions(+), 22 deletions(-)
arch/arm/mach-omap2/clock24xx.h +0 -4
index 929a257..30f3c57 100644
@@ -627,7 +627,6 @@ static struct clk func_32k_ck = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
@@ -657,7 +656,6 @@ static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 /*
@@ -709,7 +707,6 @@ static struct clk apll96_ck = {
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
 	.enable		= &omap2_clk_fixed_enable,
 	.disable	= &omap2_clk_fixed_disable,
-	.recalc		= &propagate_rate,
 };
 
 static struct clk apll54_ck = {
@@ -724,7 +721,6 @@ static struct clk apll54_ck = {
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
 	.enable		= &omap2_clk_fixed_enable,
 	.disable	= &omap2_clk_fixed_disable,
-	.recalc		= &propagate_rate,
 };
 
 /*
arch/arm/mach-omap2/clock34xx.h +0 -10
index 5357507..66cbe0c 100644
@@ -67,7 +67,6 @@ static struct clk omap_32k_fck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk secure_32k_fck = {
@@ -76,7 +75,6 @@ static struct clk secure_32k_fck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 /* Virtual source clocks for osc_sys_ck */
@@ -86,7 +84,6 @@ static struct clk virt_12m_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk virt_13m_ck = {
@@ -95,7 +92,6 @@ static struct clk virt_13m_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk virt_16_8m_ck = {
@@ -104,7 +100,6 @@ static struct clk virt_16_8m_ck = {
 	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk virt_19_2m_ck = {
@@ -113,7 +108,6 @@ static struct clk virt_19_2m_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk virt_26m_ck = {
@@ -122,7 +116,6 @@ static struct clk virt_26m_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static struct clk virt_38_4m_ck = {
@@ -131,7 +124,6 @@ static struct clk virt_38_4m_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
 				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 static const struct clksel_rate osc_sys_12m_rates[] = {
@@ -220,7 +212,6 @@ static struct clk sys_altclk = {
 	.name		= "sys_altclk",
 	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm		= { .name = "cm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 /*
@@ -232,7 +223,6 @@ static struct clk mcbsp_clks = {
 	.name		= "mcbsp_clks",
 	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
-	.recalc		= &propagate_rate,
 };
 
 /* PRM EXTERNAL CLOCK OUTPUT */
arch/arm/plat-omap/clock.c +10 -8
index 9f458cb..35064cd 100644
@@ -187,7 +187,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (arch_clock->clk_set_rate) {
 		ret = arch_clock->clk_set_rate(clk, rate);
 		if (ret == 0) {
-			(*clk->recalc)(clk);
+			if (clk->recalc)
+				(*clk->recalc)(clk);
 			if (clk->flags & RATE_PROPAGATES)
 				propagate_rate(clk);
 		}
@@ -212,7 +213,8 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (arch_clock->clk_set_parent) {
 		ret = arch_clock->clk_set_parent(clk, parent);
 		if (ret == 0) {
-			(*clk->recalc)(clk);
+			if (clk->recalc)
+				(*clk->recalc)(clk);
 			if (clk->flags & RATE_PROPAGATES)
 				propagate_rate(clk);
 		}
@@ -285,11 +287,10 @@ void propagate_rate(struct clk * tclk)
 	list_for_each_entry(clkp, &clocks, node) {
 		if (likely(clkp->parent != tclk))
 			continue;
-		if (likely((u32)clkp->recalc)) {
+		if (clkp->recalc)
 			clkp->recalc(clkp);
-			if (clkp->flags & RATE_PROPAGATES)
-				propagate_rate(clkp);
-		}
+		if (clkp->flags & RATE_PROPAGATES)
+			propagate_rate(clkp);
 	}
 }
 
@@ -305,8 +306,9 @@ void recalculate_root_clocks(void)
 	struct clk *clkp;
 
 	list_for_each_entry(clkp, &clocks, node) {
-		if (unlikely(!clkp->parent) && likely((u32)clkp->recalc)) {
-			clkp->recalc(clkp);
+		if (unlikely(!clkp->parent)) {
+			if (clkp->recalc)
+				clkp->recalc(clkp);
 			if (clkp->flags & RATE_PROPAGATES)
 				propagate_rate(clkp);
 		}
author maintainer
#4 lore raw

PATCH 4/22 OMAP clock: support "dry run" rate and parent changes

In reply to Paul Walmsley

For upcoming notifier support, modify the rate recalculation code to take parent rate and rate storage parameters. The goal here is to allow the clock code to determine what the clock's rate would be after a parent change or a rate change, without actually changing the hardware registers. This is used by the upcoming notifier patches to pass a clock's current and planned rates to the notifier callbacks.

Also add a new clock flag, RECALC_ON_ENABLE, which causes the clock framework code to recalculate the current clock's rate and propagate down the tree after a clk_enable() or clk_disable(). This is used by the OMAP3 DPLLs, which change rates when they enable or disable, unlike most clocks.

---
 arch/arm/mach-omap1/clock.c             |   74 +++++++++++++++++----
 arch/arm/mach-omap1/clock.h             |   16 +++--
 arch/arm/mach-omap2/clock.c             |   34 +++++++---
 arch/arm/mach-omap2/clock.h             |    8 +-
 arch/arm/mach-omap2/clock24xx.c         |  107 ++++++++++++++++++++++---------
 arch/arm/mach-omap2/clock24xx.h         |   13 ++--
 arch/arm/mach-omap2/clock34xx.c         |   38 ++++++++---
 arch/arm/mach-omap2/clock34xx.h         |   21 ++++--
 arch/arm/plat-omap/clock.c              |   59 ++++++++++++-----
 arch/arm/plat-omap/include/mach/clock.h |   15 +++-
 10 files changed, 277 insertions(+), 108 deletions(-)
arch/arm/mach-omap1/clock.c +57 -17
index ae2b304..f3cf6f8 100644
@@ -34,27 +34,50 @@ __u32 arm_idlect1_mask;
  * Omap1 specific clock functions
  *-------------------------------------------------------------------------*/
 
-static void omap1_watchdog_recalc(struct clk * clk)
+static void omap1_watchdog_recalc(struct clk *clk, unsigned long parent_rate,
+				  u8 rate_storage)
 {
-	clk->rate = clk->parent->rate / 14;
+	unsigned long new_rate;
+
+	new_rate = parent_rate / 14;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_rate;
 }
 
-static void omap1_uart_recalc(struct clk * clk)
+static void omap1_uart_recalc(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage)
 {
+	unsigned long new_rate;
 	unsigned int val = __raw_readl(clk->enable_reg);
+
 	if (val & clk->enable_bit)
-		clk->rate = 48000000;
+		new_rate = 48000000;
 	else
-		clk->rate = 12000000;
+		new_rate = 12000000;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_rate;
 }
 
-static void omap1_sossi_recalc(struct clk *clk)
+static void omap1_sossi_recalc(struct clk *clk, unsigned long parent_rate,
+			       u8 rate_storage)
 {
+	unsigned long new_rate;
 	u32 div = omap_readl(MOD_CONF_CTRL_1);
 
 	div = (div >> 17) & 0x7;
 	div++;
-	clk->rate = clk->parent->rate / div;
+	new_rate = clk->parent->rate / div;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_rate;
 }
 
 static int omap1_clk_enable_dsp_domain(struct clk *clk)
@@ -215,21 +238,32 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate)
 	return dsor_exp;
 }
 
-static void omap1_ckctl_recalc(struct clk * clk)
+static void omap1_ckctl_recalc(struct clk *clk, unsigned long parent_rate,
+			       u8 rate_storage)
 {
 	int dsor;
+	unsigned long new_rate;
 
 	/* Calculate divisor encoded as 2-bit exponent */
 	dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
 
-	if (unlikely(clk->rate == clk->parent->rate / dsor))
+	new_rate = parent_rate / dsor;
+
+	if (unlikely(clk->rate == new_rate))
 		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_rate;
 }
 
-static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
+static void omap1_ckctl_recalc_dsp_domain(struct clk *clk,
+					  unsigned long parent_rate,
+					  u8 rate_storage)
 {
 	int dsor;
+	unsigned long new_rate;
 
 	/* Calculate divisor encoded as 2-bit exponent
 	 *
@@ -242,9 +276,15 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
 	dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
 	omap1_clk_disable(&api_ck.clk);
 
-	if (unlikely(clk->rate == clk->parent->rate / dsor))
+	new_rate = parent_rate / dsor;
+
+	if (unlikely(clk->rate == new_rate))
 		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_rate;
 }
 
 /* MPU virtual clock functions */
@@ -283,7 +323,7 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate)
 		omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
 
 	ck_dpll1.rate = ptr->pll_rate;
-	propagate_rate(&ck_dpll1);
+	propagate_rate(&ck_dpll1, CURRENT_RATE);
 	return 0;
 }
 
@@ -724,7 +764,7 @@ int __init omap1_clk_init(void)
 			}
 		}
 	}
-	propagate_rate(&ck_dpll1);
+	propagate_rate(&ck_dpll1, CURRENT_RATE);
 #else
 	/* Find the highest supported frequency and enable it */
 	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
@@ -733,11 +773,11 @@ int __init omap1_clk_init(void)
 		omap_writew(0x2290, DPLL_CTL);
 		omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL);
 		ck_dpll1.rate = 60000000;
-		propagate_rate(&ck_dpll1);
+		propagate_rate(&ck_dpll1, CURRENT_RATE);
 	}
 #endif
 	/* Cache rates for clocks connected to ck_ref (not dpll1) */
-	propagate_rate(&ck_ref);
+	propagate_rate(&ck_ref, CURRENT_RATE);
 	printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
 		"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
 	       ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
arch/arm/mach-omap1/clock.h +11 -5
index 44eda0f..c69f265 100644
@@ -15,16 +15,22 @@
 
 static int omap1_clk_enable_generic(struct clk * clk);
 static void omap1_clk_disable_generic(struct clk * clk);
-static void omap1_ckctl_recalc(struct clk * clk);
-static void omap1_watchdog_recalc(struct clk * clk);
+static void omap1_ckctl_recalc(struct clk *clk, unsigned long parent_rate,
+			       u8 rate_storage);
+static void omap1_watchdog_recalc(struct clk *clk, unsigned long parent_rate,
+				  u8 rate_storage);
 static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate);
-static void omap1_sossi_recalc(struct clk *clk);
-static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
+static void omap1_sossi_recalc(struct clk *clk, unsigned long parent_rate,
+			       u8 rate_storage);
+static void omap1_ckctl_recalc_dsp_domain(struct clk *clk,
+					  unsigned long parent_rate,
+					  u8 rate_storage);
 static int omap1_clk_enable_dsp_domain(struct clk * clk);
 static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate);
 static void omap1_clk_disable_dsp_domain(struct clk * clk);
 static int omap1_set_uart_rate(struct clk * clk, unsigned long rate);
-static void omap1_uart_recalc(struct clk * clk);
+static void omap1_uart_recalc(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage);
 static int omap1_clk_enable_uart_functional(struct clk * clk);
 static void omap1_clk_disable_uart_functional(struct clk * clk);
 static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate);
arch/arm/mach-omap2/clock.c +24 -10
index 13db3d5..f45cc88 100644
@@ -241,6 +241,7 @@ void omap2_init_clksel_parent(struct clk *clk)
 /**
  * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
  * @clk: struct clk * of a DPLL
+ * @parent_rate: rate of the parent of the DPLL clock
  *
  * DPLLs can be locked or bypassed - basically, enabled or disabled.
  * When locked, the DPLL output depends on the M and N values.  When
@@ -252,7 +253,7 @@ void omap2_init_clksel_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.
  */
-u32 omap2_get_dpll_rate(struct clk *clk)
+u32 omap2_get_dpll_rate(struct clk *clk, unsigned long parent_rate)
 {
 	long long dpll_clk;
 	u32 dpll_mult, dpll_div, v;
@@ -271,7 +272,7 @@ u32 omap2_get_dpll_rate(struct clk *clk)
 
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-			return clk->parent->rate;
+			return parent_rate;
 
 	} else if (cpu_is_omap34xx()) {
 
@@ -287,7 +288,7 @@ u32 omap2_get_dpll_rate(struct clk *clk)
 	dpll_div = v & dd->div1_mask;
 	dpll_div >>= __ffs(dd->div1_mask);
 
-	dpll_clk = (long long)clk->parent->rate * dpll_mult;
+	dpll_clk = (long long)parent_rate * dpll_mult;
 	do_div(dpll_clk, dpll_div + 1);
 
 	return dpll_clk;
@@ -297,11 +298,19 @@ u32 omap2_get_dpll_rate(struct clk *clk)
  * Used for clocks that have the same value as the parent clock,
  * divided by some factor
  */
-void omap2_fixed_divisor_recalc(struct clk *clk)
+void omap2_fixed_divisor_recalc(struct clk *clk, unsigned long parent_rate,
+				u8 rate_storage)
 {
-	WARN_ON(!clk->fixed_div);
+	unsigned long rate;
 
-	clk->rate = clk->parent->rate / clk->fixed_div;
+	WARN_ON(!clk->fixed_div); /* XXX move this to init */
+
+	rate = parent_rate / clk->fixed_div;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
 /**
@@ -488,9 +497,11 @@ int omap2_clk_enable(struct clk *clk)
  * Used for clocks that are part of CLKSEL_xyz governed clocks.
  * REVISIT: Maybe change to use clk->enable() functions like on omap1?
  */
-void omap2_clksel_recalc(struct clk *clk)
+void omap2_clksel_recalc(struct clk *clk, unsigned long parent_rate,
+			 u8 rate_storage)
 {
 	u32 div = 0;
+	unsigned long rate;
 
 	pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
 
@@ -498,9 +509,12 @@ void omap2_clksel_recalc(struct clk *clk)
 	if (div == 0)
 		return;
 
-	if (clk->rate == (clk->parent->rate / div))
-		return;
-	clk->rate = clk->parent->rate / div;
+	rate = parent_rate / div;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 
 	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
 }
arch/arm/mach-omap2/clock.h +5 -3
index faff95e..a026ec9 100644
@@ -52,7 +52,8 @@ void omap2_clk_disable_unused(struct clk *clk);
 #define omap2_clk_disable_unused	NULL
 #endif
 
-void omap2_clksel_recalc(struct clk *clk);
+void omap2_clksel_recalc(struct clk *clk, unsigned long new_parent_rate,
+			 u8 rate_storage);
 void omap2_init_clk_clkdm(struct clk *clk);
 void omap2_init_clksel_parent(struct clk *clk);
 u32 omap2_clksel_get_divisor(struct clk *clk);
@@ -60,10 +61,11 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 				u32 *new_div);
 u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
 u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
-void omap2_fixed_divisor_recalc(struct clk *clk);
+void omap2_fixed_divisor_recalc(struct clk *clk, unsigned long new_parent_rate,
+				u8 rate_storage);
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
-u32 omap2_get_dpll_rate(struct clk *clk);
+u32 omap2_get_dpll_rate(struct clk *clk, unsigned long parent_rate);
 int omap2_wait_clock_ready(s16 prcm_mod, u16 idlest_reg, u32 cval,
 			   const char *name);
 void omap2_clk_prepare_for_reboot(void);
arch/arm/mach-omap2/clock24xx.c +77 -30

187 lines not on this page · raw message

arch/arm/mach-omap2/clock24xx.h +8 -5
index 30f3c57..cd9feda 100644
@@ -24,13 +24,16 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 
-static void omap2_table_mpu_recalc(struct clk *clk);
+static void omap2_table_mpu_recalc(struct clk *clk, unsigned long parent_rate,
+				   u8 rate_storage);
 static int omap2_select_table_rate(struct clk *clk, unsigned long rate);
 static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
-static void omap2_sys_clk_recalc(struct clk *clk);
-static void omap2_osc_clk_recalc(struct clk *clk);
-static void omap2_sys_clk_recalc(struct clk *clk);
-static void omap2_dpllcore_recalc(struct clk *clk);
+static void omap2_sys_clk_recalc(struct clk *clk, unsigned long parent_rate,
+				 u8 rate_storage);
+static void omap2_osc_clk_recalc(struct clk *clk, unsigned long parent_rate,
+				 u8 rate_storage);
+static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate,
+				 u8 rate_storage);
 static int omap2_clk_fixed_enable(struct clk *clk);
 static void omap2_clk_fixed_disable(struct clk *clk);
 static int omap2_enable_osc_ck(struct clk *clk);
arch/arm/mach-omap2/clock34xx.c +27 -11
index 22cbcce..917664d 100644
@@ -48,12 +48,22 @@
 /**
  * omap3_dpll_recalc - recalculate DPLL rate
  * @clk: DPLL struct clk
+ * @parent_rate: rate of the DPLL's parent clock
+ * @rate_storage: flag indicating whether current or temporary rate is changing
  *
  * Recalculate and propagate the DPLL rate.
  */
-static void omap3_dpll_recalc(struct clk *clk)
+static void omap3_dpll_recalc(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage)
 {
-	clk->rate = omap2_get_dpll_rate(clk);
+	unsigned long rate;
+
+	rate = omap2_get_dpll_rate(clk, parent_rate);
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -278,9 +288,6 @@ static int omap3_noncore_dpll_enable(struct clk *clk)
 	else
 		r = _omap3_noncore_dpll_lock(clk);
 
-	if (!r)
-		clk->rate = omap2_get_dpll_rate(clk);
-
 	return r;
 }
 
@@ -392,7 +399,7 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 	if (!dd)
 		return -EINVAL;
 
-	if (rate == omap2_get_dpll_rate(clk))
+	if (rate == omap2_get_dpll_rate(clk, clk->parent->rate))
 		return 0;
 
 	if (dd->bypass_clk->rate == rate &&
@@ -578,14 +585,18 @@ static void omap3_dpll_deny_idle(struct clk *clk)
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
+ * @parent_rate: rate of the parent clock of @clk
+ * @rate_storage: flag indicating whether current or temporary rate is changing
  *
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
-static void omap3_clkoutx2_recalc(struct clk *clk)
+static void omap3_clkoutx2_recalc(struct clk *clk, unsigned long parent_rate,
+				  u8 rate_storage)
 {
 	const struct dpll_data *dd;
 	u32 v;
+	unsigned long rate;
 	struct clk *pclk;
 
 	/* Walk up the parents of clk, looking for a DPLL */
@@ -600,12 +611,17 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
 
 	WARN_ON(!dd->enable_mask);
 
+	rate = parent_rate;
+
 	v = cm_read_mod_reg(pclk->prcm_mod, dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
-	if (v != OMAP3XXX_EN_DPLL_LOCKED)
-		clk->rate = clk->parent->rate;
-	else
-		clk->rate = clk->parent->rate * 2;
+	if (v == OMAP3XXX_EN_DPLL_LOCKED)
+		rate *= 2;
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
 /* Common clock code */
arch/arm/mach-omap2/clock34xx.h +14 -7
index 66cbe0c..283c386 100644
@@ -27,8 +27,10 @@
 #include "prm.h"
 #include "prm-regbits-34xx.h"
 
-static void omap3_dpll_recalc(struct clk *clk);
-static void omap3_clkoutx2_recalc(struct clk *clk);
+static void omap3_dpll_recalc(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage);
+static void omap3_clkoutx2_recalc(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage);
 static void omap3_dpll_allow_idle(struct clk *clk);
 static void omap3_dpll_deny_idle(struct clk *clk);
 static u32 omap3_dpll_autoidle_read(struct clk *clk);
@@ -292,7 +294,8 @@ static struct clk dpll1_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= MPU_MOD,
 	.dpll_data	= &dpll1_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
+			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 	.clkdm		= { .name = "dpll1_clkdm" },
@@ -368,7 +371,8 @@ static struct clk dpll2_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= OMAP3430_IVA2_MOD,
 	.dpll_data	= &dpll2_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
+			  RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -431,7 +435,8 @@ static struct clk dpll3_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll3_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
+			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_dpll_recalc,
@@ -597,7 +602,8 @@ static struct clk dpll4_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll4_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
+			  RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -926,7 +932,8 @@ static struct clk dpll5_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll5_dd,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
+			  RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
arch/arm/plat-omap/clock.c +43 -16

114 lines not on this page · raw message

arch/arm/plat-omap/include/mach/clock.h +11 -4
index e793616..9b1d1f8 100644
@@ -67,12 +67,13 @@ struct clk {
 	int			id;
 	struct clk		*parent;
 	unsigned long		rate;
+	unsigned long		temp_rate;
 	__u32			flags;
 	u32			enable_reg;
 	__u8			enable_bit;
 	__s8			usecount;
 	u8			idlest_bit;
-	void			(*recalc)(struct clk *);
+	void			(*recalc)(struct clk *, unsigned long, u8);
 	int			(*set_rate)(struct clk *, unsigned long);
 	long			(*round_rate)(struct clk *, unsigned long);
 	void			(*init)(struct clk *);
@@ -120,9 +121,10 @@ extern unsigned int mpurate;
 extern int clk_init(struct clk_functions *custom_clocks);
 extern int clk_register(struct clk *clk);
 extern void clk_unregister(struct clk *clk);
-extern void propagate_rate(struct clk *clk);
+extern void propagate_rate(struct clk *clk, u8 rate_storage);
 extern void recalculate_root_clocks(void);
-extern void followparent_recalc(struct clk *clk);
+extern void followparent_recalc(struct clk *clk, unsigned long parent_rate,
+				u8 rate_storage);
 extern void clk_allow_idle(struct clk *clk);
 extern void clk_deny_idle(struct clk *clk);
 extern int clk_get_usecount(struct clk *clk);
@@ -146,7 +148,8 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 #define ENABLE_ON_INIT		(1 << 11)	/* Enable upon framework init */
 #define INVERT_ENABLE		(1 << 12)	/* 0 enables, 1 disables */
 #define WAIT_READY		(1 << 13)	/* wait for dev to leave idle */
-/* bits 14-20 are currently free */
+#define RECALC_ON_ENABLE	(1 << 14)	/* recalc/prop on ena/disa */
+/* bits 15-20 are currently free */
 #define CLOCK_IN_OMAP310	(1 << 21)
 #define CLOCK_IN_OMAP730	(1 << 22)
 #define CLOCK_IN_OMAP1510	(1 << 23)
@@ -167,6 +170,10 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
 
+/* rate_storage parameter flags */
+#define CURRENT_RATE		0
+#define TEMP_RATE		1
+
 /*
  * clk.prcm_mod flags (possible since only the top byte in clk.prcm_mod
  * is significant)
author maintainer
#5 lore raw

PATCH 5/22 OMAP clock: track child clocks

In reply to Paul Walmsley

Track child clocks for each struct clk. This optimizes traversals of the clock tree from parent to child, which happens during rate propagation, and in the future, clock notifiers.

Previously, parent-to-child traversals sequentially scanned the entire clock list at each step to determine the children of a particular clock node. Now each struct clk maintains a clock list of its children. For a DPLL3_M2_CK rate change, this converts what were about O(6*180*2) operations into O(6*6*2) operations. The savings will be even more significant after the future notifier patches:
something like O(6*180*6) to O(6*6*6).

The price paid is additional runtime memory consumption - 8 bytes per clock and 16 bytes per child clock - roughly 4.5KiB on OMAP3. The memory comes mostly from bootmem, since initial clock registration takes place before slab is ready. Several other operations will take slightly more time due the extra bookkeeping: clk_register(), clk_unregister(), clk_set_parent(), and omap2_init_clksel_parent().

---
 arch/arm/mach-omap2/clock.c             |    4 +
 arch/arm/plat-omap/clock.c              |  221 ++++++++++++++++++++++++-------
 arch/arm/plat-omap/include/mach/clock.h |   18 +++
 3 files changed, 195 insertions(+), 48 deletions(-)
arch/arm/mach-omap2/clock.c +4 -0
index f45cc88..4d04e9f 100644
@@ -224,7 +224,11 @@ void omap2_init_clksel_parent(struct clk *clk)
 						 clk->name, clks->parent->name,
 						 ((clk->parent) ?
 						  clk->parent->name : "NULL"));
+					if (clk->parent)
+						omap_clk_del_child(clk->parent,
+								   clk);
 					clk->parent = clks->parent;
+					omap_clk_add_child(clk->parent, clk);
 				};
 				found = 1;
 			}
arch/arm/plat-omap/clock.c +173 -48

300 lines not on this page · raw message

arch/arm/plat-omap/include/mach/clock.h +18 -0
index 9b1d1f8..fe568a7 100644
@@ -60,6 +60,17 @@ struct dpll_data {
 
 #endif
 
+/**
+ * struct clk_child - used to track the children of a clock
+ *
+ * XXX doco
+ */
+struct clk_child {
+	struct clk		*clk;
+	struct list_head	node;
+	u8			flags;
+};
+
 struct clk {
 	struct list_head	node;
 	struct module		*owner;
@@ -68,6 +79,7 @@ struct clk {
 	struct clk		*parent;
 	unsigned long		rate;
 	unsigned long		temp_rate;
+	struct list_head	children;
 	__u32			flags;
 	u32			enable_reg;
 	__u8			enable_bit;
@@ -132,6 +144,8 @@ extern void clk_enable_init_clocks(void);
 #ifdef CONFIG_CPU_FREQ
 extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 #endif
+void omap_clk_add_child(struct clk *clk, struct clk *clk2);
+void omap_clk_del_child(struct clk *clk, struct clk *clk2);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
@@ -174,6 +188,10 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 #define CURRENT_RATE		0
 #define TEMP_RATE		1
 
+/* clk_child flags */
+#define CLK_CHILD_SLAB_ALLOC	(1 << 0)	/* if !set, bootmem was used */
+#define CLK_CHILD_DELETED	(1 << 1)	/* can be reused */
+
 /*
  * clk.prcm_mod flags (possible since only the top byte in clk.prcm_mod
  * is significant)
author maintainer
#6 lore raw

PATCH 6/22 OMAP clock: drop the RATE_PROPAGATES flag

In reply to Paul Walmsley

Now that clocks keep track of their children, the RATE_PROPAGATES flag is no longer necessary.

---
 arch/arm/mach-omap1/clock.h             |    9 +
 arch/arm/mach-omap2/clock24xx.h         |   41 +++---
 arch/arm/mach-omap2/clock34xx.h         |  216 +++++++++++--------------------
 arch/arm/plat-omap/include/mach/clock.h |    2 
 4 files changed, 104 insertions(+), 164 deletions(-)
arch/arm/mach-omap1/clock.h +4 -5
index c69f265..d9f34d3 100644
@@ -169,7 +169,7 @@ static struct clk ck_dpll1 = {
 	.name		= "ck_dpll1",
 	.parent		= &ck_ref,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -179,7 +179,7 @@ static struct arm_idlect1_clk ck_dpll1out = {
 		.name		= "ck_dpll1out",
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL |
-				  ENABLE_REG_32BIT | RATE_PROPAGATES,
+				  ENABLE_REG_32BIT,
 		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_CKOUT_ARM,
 		.recalc		= &followparent_recalc,
@@ -206,8 +206,7 @@ static struct clk arm_ck = {
 	.name		= "arm_ck",
 	.parent		= &ck_dpll1,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
-			  ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | RATE_CKCTL | ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_ARMDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
 	.enable		= &omap1_clk_enable_generic,
@@ -368,7 +367,7 @@ static struct arm_idlect1_clk tc_ck = {
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
 				  CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
-				  RATE_CKCTL | RATE_PROPAGATES |
+				  RATE_CKCTL |
 				  ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
 		.rate_offset	= CKCTL_TCDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
arch/arm/mach-omap2/clock24xx.h +19 -22

155 lines not on this page · raw message

arch/arm/mach-omap2/clock34xx.h +80 -136

696 lines not on this page · raw message

arch/arm/plat-omap/include/mach/clock.h +1 -1
index fe568a7..a689430 100644
@@ -150,7 +150,7 @@ void omap_clk_del_child(struct clk *clk, struct clk *clk2);
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
 #define RATE_FIXED		(1 << 1)	/* Fixed clock rate */
-#define RATE_PROPAGATES		(1 << 2)	/* Program children too */
+
 #define VIRTUAL_CLOCK		(1 << 3)	/* Composite clock from table */
 #define ALWAYS_ENABLED		(1 << 4)	/* Clock cannot be disabled */
 #define ENABLE_REG_32BIT	(1 << 5)	/* Use 32-bit access */
author maintainer
#7 lore raw

PATCH 7/22 OMAP clock: drop RATE_FIXED

In reply to Paul Walmsley

The RATE_FIXED flag currently has no useful purpose. Fixed rate clocks should simply not implement the recalc, set_rate, set_parent, and round_rate function pointers.

---
 arch/arm/mach-omap1/clock.c             |    3 ---
 arch/arm/mach-omap1/clock.h             |   31 +++++++++++++++----------------
 arch/arm/mach-omap2/clock.c             |    4 ----
 arch/arm/mach-omap2/clock24xx.h         |    8 ++++----
 arch/arm/mach-omap2/clock34xx.h         |   19 +++++++++----------
 arch/arm/plat-omap/include/mach/clock.h |    2 +-
 6 files changed, 29 insertions(+), 38 deletions(-)
arch/arm/mach-omap1/clock.c +0 -3
index f3cf6f8..af48050 100644
@@ -570,9 +570,6 @@ static long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	int dsor_exp;
 
-	if (clk->flags & RATE_FIXED)
-		return clk->rate;
-
 	if (clk->flags & RATE_CKCTL) {
 		dsor_exp = calc_dsor_exp(clk, rate);
 		if (dsor_exp < 0)
arch/arm/mach-omap1/clock.h +15 -16
index d9f34d3..564f4bc 100644
@@ -554,8 +554,8 @@ static struct uart_clk uart1_16xx = {
 		/* Direct from ULPD, no real parent */
 		.parent		= &armper_ck.clk,
 		.rate		= 48000000,
-		.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED |
-				  ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+		.flags		= CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
+				  CLOCK_NO_IDLE_PARENT,
 		.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 		.enable_bit	= 29,
 		.enable		= &omap1_clk_enable_uart_functional,
@@ -602,8 +602,8 @@ static struct uart_clk uart3_16xx = {
 		/* Direct from ULPD, no real parent */
 		.parent		= &armper_ck.clk,
 		.rate		= 48000000,
-		.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED |
-				  ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+		.flags		= CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
+				  CLOCK_NO_IDLE_PARENT,
 		.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 		.enable_bit	= 31,
 		.enable		= &omap1_clk_enable_uart_functional,
@@ -617,7 +617,7 @@ static struct clk usb_clko = {	/* 6 MHz output on W4_USB_CLKO */
 	/* Direct from ULPD, no parent */
 	.rate		= 6000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
+			  CLOCK_IN_OMAP310 | ENABLE_REG_32BIT,
 	.enable_reg	= OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL),
 	.enable_bit	= USB_MCLK_EN_BIT,
 	.enable		= &omap1_clk_enable_generic,
@@ -629,7 +629,7 @@ static struct clk usb_hhc_ck1510 = {
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  RATE_FIXED | ENABLE_REG_32BIT,
+			  ENABLE_REG_32BIT,
 	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= USB_HOST_HHC_UHOST_EN,
 	.enable		= &omap1_clk_enable_generic,
@@ -641,8 +641,7 @@ static struct clk usb_hhc_ck16xx = {
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000,
 	/* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
-	.flags		= CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT,
+	.flags		= CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT,
 	.enable_reg	= OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */
 	.enable_bit	= 8 /* UHOST_EN */,
 	.enable		= &omap1_clk_enable_generic,
@@ -653,7 +652,7 @@ static struct clk usb_dc_ck = {
 	.name		= "usb_dc_ck",
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000,
-	.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED,
+	.flags		= CLOCK_IN_OMAP16XX,
 	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
 	.enable_bit	= 4,
 	.enable		= &omap1_clk_enable_generic,
@@ -664,9 +663,9 @@ static struct clk mclk_1510 = {
 	.name		= "mclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
- 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
- 	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
- 	.enable_bit	= 6,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
+	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+	.enable_bit	= 6,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -688,7 +687,7 @@ static struct clk bclk_1510 = {
 	.name		= "bclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -712,7 +711,7 @@ static struct clk mmc1_ck = {
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+			  CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
 			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 23,
@@ -726,8 +725,8 @@ static struct clk mmc2_ck = {
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
-	.flags		= CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.flags		= CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 20,
 	.enable		= &omap1_clk_enable_generic,
arch/arm/mach-omap2/clock.c +0 -4
index 4d04e9f..31b5c9d 100644
@@ -644,10 +644,6 @@ long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
 	if (clk->round_rate != NULL)
 		return clk->round_rate(clk, rate);
 
-	if (clk->flags & RATE_FIXED)
-		printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
-		       "on fixed-rate clock %s\n", clk->name);
-
 	return clk->rate;
 }
 
arch/arm/mach-omap2/clock24xx.h +4 -4
index 88ba9cf..824413d 100644
@@ -628,7 +628,7 @@ static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.rate		= 32000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -656,7 +656,7 @@ static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
 	.name		= "alt_ck",
 	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -703,7 +703,7 @@ static struct clk apll96_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 96000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
@@ -717,7 +717,7 @@ static struct clk apll54_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
arch/arm/mach-omap2/clock34xx.h +9 -10
index 2fde89e..179ea17 100644
@@ -66,14 +66,14 @@ static struct clk dpll2_fck;
 static struct clk omap_32k_fck = {
 	.name		= "omap_32k_fck",
 	.rate		= 32768,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk secure_32k_fck = {
 	.name		= "secure_32k_fck",
 	.rate		= 32768,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -81,42 +81,42 @@ static struct clk secure_32k_fck = {
 static struct clk virt_12m_ck = {
 	.name		= "virt_12m_ck",
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk virt_13m_ck = {
 	.name		= "virt_13m_ck",
 	.rate		= 13000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk virt_16_8m_ck = {
 	.name		= "virt_16_8m_ck",
 	.rate		= 16800000,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP3430ES2 | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk virt_19_2m_ck = {
 	.name		= "virt_19_2m_ck",
 	.rate		= 19200000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk virt_26m_ck = {
 	.name		= "virt_26m_ck",
 	.rate		= 26000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 static struct clk virt_38_4m_ck = {
 	.name		= "virt_38_4m_ck",
 	.rate		= 38400000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -170,8 +170,7 @@ static struct clk osc_sys_ck = {
 	.clksel_mask	= OMAP3430_SYS_CLKIN_SEL_MASK,
 	.clksel		= osc_sys_clksel,
 	/* REVISIT: deal with autoextclkmode? */
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
arch/arm/plat-omap/include/mach/clock.h +1 -1
index a689430..f4fab45 100644
@@ -149,7 +149,7 @@ void omap_clk_del_child(struct clk *clk, struct clk *clk2);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
-#define RATE_FIXED		(1 << 1)	/* Fixed clock rate */
+
 
 #define VIRTUAL_CLOCK		(1 << 3)	/* Composite clock from table */
 #define ALWAYS_ENABLED		(1 << 4)	/* Clock cannot be disabled */
author maintainer
#8 lore raw

PATCH 8/22 OMAP clock: remove VIRTUAL_CLOCK

In reply to Paul Walmsley

From: Russell King <[email protected]>

Nothing tests the clock flags for this bit, so it serves no purpose. Remove it.

---
 arch/arm/mach-omap1/clock.h             |    8 +++-----
 arch/arm/mach-omap2/clock24xx.h         |    2 +-
 arch/arm/plat-omap/include/mach/clock.h |    6 ++----
 3 files changed, 6 insertions(+), 10 deletions(-)
arch/arm/mach-omap1/clock.h +3 -5
index 564f4bc..5ba55a0 100644
@@ -736,7 +736,7 @@ static struct clk mmc2_ck = {
 static struct clk virtual_ck_mpu = {
 	.name		= "mpu",
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.parent		= &arm_ck, /* Is smarter alias for */
 	.recalc		= &followparent_recalc,
 	.set_rate	= &omap1_select_table_rate,
@@ -751,8 +751,7 @@ static struct clk i2c_fck = {
 	.name		= "i2c_fck",
 	.id		= 1,
 	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
-			  ALWAYS_ENABLED,
+			  CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED,
 	.parent		= &armxor_ck.clk,
 	.recalc		= &followparent_recalc,
 	.enable		= &omap1_clk_enable_generic,
@@ -762,8 +761,7 @@ static struct clk i2c_fck = {
 static struct clk i2c_ick = {
 	.name		= "i2c_ick",
 	.id		= 1,
-	.flags		= CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+	.flags		= CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT |
 			  ALWAYS_ENABLED,
 	.parent		= &armper_ck.clk,
 	.recalc		= &followparent_recalc,
arch/arm/mach-omap2/clock24xx.h +1 -1
index 824413d..8e0b3f7 100644
@@ -2845,7 +2845,7 @@ static struct clk mmchsdb2_fck = {
 static struct clk virt_prcm_set = {
 	.name		= "virt_prcm_set",
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
+				ALWAYS_ENABLED | DELAYED_APP,
 	.clkdm		= { .name = "virt_opp_clkdm" },
 	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
 	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
arch/arm/plat-omap/include/mach/clock.h +2 -4
index f4fab45..57b33c3 100644
@@ -149,12 +149,10 @@ void omap_clk_del_child(struct clk *clk, struct clk *clk2);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
-
-
-#define VIRTUAL_CLOCK		(1 << 3)	/* Composite clock from table */
+/* bits 1-3 are currently free */
 #define ALWAYS_ENABLED		(1 << 4)	/* Clock cannot be disabled */
 #define ENABLE_REG_32BIT	(1 << 5)	/* Use 32-bit access */
-
+/* bit 6 is currently free */
 #define CLOCK_IDLE_CONTROL	(1 << 7)
 #define CLOCK_NO_IDLE_PARENT	(1 << 8)
 #define DELAYED_APP		(1 << 9)	/* Delay application of clock */
author maintainer
#9 lore raw

PATCH 9/22 OMAP2 clock: drop CONFIG_PARTICIPANT clock flag

In reply to Paul Walmsley

The CONFIG_PARTICIPANT flags indicates to the clock rate and parent changing functions that they should not be used on this clock. Better just to remove the clock function pointers that operate on those clocks. The name of the flag is just terrible: its meaning has almost nothing to do with its name, and the use of the CONFIG_ prefix makes it appear to be a Kconfig option. Get rid of it.

---
 arch/arm/mach-omap2/clock.c             |   13 -----------
 arch/arm/mach-omap2/clock24xx.h         |   37 +++++++++----------------------
 arch/arm/plat-omap/include/mach/clock.h |    2 +-
 3 files changed, 12 insertions(+), 40 deletions(-)
arch/arm/mach-omap2/clock.c +0 -13
index 31b5c9d..8599b34 100644
@@ -563,8 +563,6 @@ static const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
  *
  * Finds 'best' divider value in an array based on the source and target
  * rates.  The divider array must be sorted with smallest divider first.
- * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
- * they are only settable as part of virtual_prcm set.
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
@@ -625,8 +623,6 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
  * Compatibility wrapper for OMAP clock framework
  * Finds best target rate based on the source clock and possible dividers.
  * rates. The divider array must be sorted with smallest divider first.
- * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
- * they are only settable as part of virtual_prcm set.
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
@@ -778,12 +774,6 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
 
 	pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
 
-	/* CONFIG_PARTICIPANT clocks are changed only in sets via the
-	   rate table mechanism, driven by mpu_speed  */
-	if (clk->flags & CONFIG_PARTICIPANT)
-		return -EINVAL;
-
-	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
 	if (clk->set_rate != NULL)
 		ret = clk->set_rate(clk, rate);
 
@@ -828,9 +818,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 {
 	u32 field_val, v, parent_div;
 
-	if (clk->flags & CONFIG_PARTICIPANT)
-		return -EINVAL;
-
 	if (!clk->clksel)
 		return -EINVAL;
 
arch/arm/mach-omap2/clock24xx.h +11 -26
index 8e0b3f7..2b7b473 100644
@@ -1018,16 +1018,13 @@ static struct clk mpu_ck = {	/* Control cpu */
 	.parent		= &core_ck,
 	.prcm_mod	= MPU_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP |
-				CONFIG_PARTICIPANT,
+				ALWAYS_ENABLED | DELAYED_APP,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
 	.clksel		= mpu_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 /*
@@ -1061,8 +1058,7 @@ static struct clk dsp_fck = {
 	.name		= "dsp_fck",
 	.parent		= &core_ck,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
-				CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP,
 	.clkdm		= { .name = "dsp_clkdm" },
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
@@ -1070,8 +1066,6 @@ static struct clk dsp_fck = {
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
 	.clksel		= dsp_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 /* DSP interface clock */
@@ -1093,14 +1087,12 @@ static struct clk dsp_irate_ick = {
 	.parent		= &dsp_fck,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
-				CONFIG_PARTICIPANT | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dsp_clkdm" },
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
 	.clksel		= dsp_irate_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 /* 2420 only */
@@ -1108,7 +1100,7 @@ static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
 	.parent		= &dsp_irate_ick,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
 	.clkdm		= { .name = "dsp_clkdm" },
 	.enable_reg	= CM_ICLKEN,
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
@@ -1119,7 +1111,7 @@ static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.parent		= &dsp_irate_ick,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP,
 	.clkdm		= { .name = "dsp_clkdm" },
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
@@ -1134,7 +1126,7 @@ static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
 	.clkdm		= { .name = "iva1_clkdm" },
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
@@ -1199,15 +1191,12 @@ static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
 	.parent		= &core_ck,
 	.prcm_mod	= CORE_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP |
-				CONFIG_PARTICIPANT,
+				ALWAYS_ENABLED | DELAYED_APP,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
 	.clksel		= core_l3_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 /* usb_l4_ick */
@@ -1228,8 +1217,8 @@ static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
 	.parent		= &core_l3_ck,
 	.prcm_mod	= CORE_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				DELAYED_APP | CONFIG_PARTICIPANT | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | WAIT_READY |
+				DELAYED_APP,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.enable_reg	= CM_ICLKEN2,
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
@@ -1238,8 +1227,6 @@ static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
 	.clksel		= usb_l4_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 /*
@@ -1345,7 +1332,7 @@ static struct clk ssi_l4_ick = {
  * divided value of fclk.
  *
  */
-/* XXX REVISIT: GFX clock is part of CONFIG_PARTICIPANT, no? doublecheck. */
+/* XXX REVISIT: GFX clock is part of the table rate set also? doublecheck. */
 
 /* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
 static const struct clksel gfx_fck_clksel[] = {
@@ -1420,7 +1407,7 @@ static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
 	.parent		= &core_ck,
 	.prcm_mod	= OMAP2430_MDM_MOD,
-	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP,
 	.clkdm		= { .name = "mdm_clkdm" },
 	.enable_reg	= CM_ICLKEN,
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
@@ -1428,8 +1415,6 @@ static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.clksel_mask	= OMAP2430_CLKSEL_MDM_MASK,
 	.clksel		= mdm_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
 };
 
 static struct clk mdm_osc_ck = {
arch/arm/plat-omap/include/mach/clock.h +1 -1
index 57b33c3..91ebf9e 100644
@@ -156,7 +156,7 @@ void omap_clk_del_child(struct clk *clk, struct clk *clk2);
 #define CLOCK_IDLE_CONTROL	(1 << 7)
 #define CLOCK_NO_IDLE_PARENT	(1 << 8)
 #define DELAYED_APP		(1 << 9)	/* Delay application of clock */
-#define CONFIG_PARTICIPANT	(1 << 10)	/* Fundamental clock */
+/* bit 10 is currently free */
 #define ENABLE_ON_INIT		(1 << 11)	/* Enable upon framework init */
 #define INVERT_ENABLE		(1 << 12)	/* 0 enables, 1 disables */
 #define WAIT_READY		(1 << 13)	/* wait for dev to leave idle */
author maintainer
#10 lore raw

PATCH 10/22 OMAP2/3 clock: remove clk->owner

In reply to Paul Walmsley

From: Russell King <[email protected]>

clk->owner is always NULL, so its existence doesn't serve any useful function other than bloating the kernel by 992 bytes. Remove it.

---
 arch/arm/plat-omap/clock.c              |    7 ++-----
 arch/arm/plat-omap/include/mach/clock.h |    1 -
 2 files changed, 2 insertions(+), 6 deletions(-)
arch/arm/plat-omap/clock.c +2 -5
index 80eb558..ab3d879 100644
@@ -191,15 +191,14 @@ struct clk * clk_get(struct device *dev, const char *id)
 	mutex_lock(&clocks_mutex);
 
 	list_for_each_entry(p, &clocks, node) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+		if (p->id == idno && strcmp(id, p->name) == 0) {
 			clk = p;
 			goto found;
 		}
 	}
 
 	list_for_each_entry(p, &clocks, node) {
-		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+		if (strcmp(id, p->name) == 0) {
 			clk = p;
 			break;
 		}
@@ -295,8 +294,6 @@ EXPORT_SYMBOL(clk_get_rate);
 
 void clk_put(struct clk *clk)
 {
-	if (clk && !IS_ERR(clk))
-		module_put(clk->owner);
 }
 EXPORT_SYMBOL(clk_put);
 
arch/arm/plat-omap/include/mach/clock.h +0 -1
index 91ebf9e..bc28780 100644
@@ -73,7 +73,6 @@ struct clk_child {
 
 struct clk {
 	struct list_head	node;
-	struct module		*owner;
 	const char		*name;
 	int			id;
 	struct clk		*parent;
author maintainer
#11 lore raw

PATCH 11/22 OMAP clock: rearrange clock.h structure order

In reply to Paul Walmsley

From: Russell King <[email protected]>

... to eliminate unnecessary padding. We have rather a lot of these structures, so eliminating unnecessary padding results in a saving of 1488 bytes.

[[email protected]: updated against current linux-omap clock tree, now saves 1512 bytes on OMAP3 builds]

---
 arch/arm/plat-omap/include/mach/clock.h |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)
arch/arm/plat-omap/include/mach/clock.h +15 -15
index bc28780..2f1c5cd 100644
@@ -20,8 +20,8 @@ struct clockdomain;
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 
 struct clksel_rate {
-	u8			div;
 	u32			val;
+	u8			div;
 	u8			flags;
 };
 
@@ -31,30 +31,30 @@ struct clksel {
 };
 
 struct dpll_data {
-	u16			mult_div1_reg;
 	u32			mult_mask;
 	u32			div1_mask;
-	u16			last_rounded_m;
-	u8			last_rounded_n;
 	unsigned long		last_rounded_rate;
 	unsigned int		rate_tolerance;
-	u16			max_multiplier;
-	u8			min_divider;
-	u8			max_divider;
 	u32			max_tolerance;
 	struct clk		*bypass_clk;
-	u16			control_reg;
 	u32			enable_mask;
+	u16			mult_div1_reg;
+	u16			control_reg;
+	u16			max_multiplier;
+	u16			last_rounded_m;
+	u8			last_rounded_n;
+	u8			min_divider;
+	u8			max_divider;
 #  if defined(CONFIG_ARCH_OMAP3)
-	u16			idlest_reg;
-	u32			idlest_mask;
-	u32			freqsel_mask;
 	u8			modes;
 	u8			auto_recal_bit;
 	u8			recal_en_bit;
 	u8			recal_st_bit;
 	u16			autoidle_reg;
+	u16			idlest_reg;
 	u32			autoidle_mask;
+	u32			idlest_mask;
+	u32			freqsel_mask;
 #  endif
 };
 
@@ -81,18 +81,17 @@ struct clk {
 	struct list_head	children;
 	__u32			flags;
 	u32			enable_reg;
-	__u8			enable_bit;
-	__s8			usecount;
-	u8			idlest_bit;
 	void			(*recalc)(struct clk *, unsigned long, u8);
 	int			(*set_rate)(struct clk *, unsigned long);
 	long			(*round_rate)(struct clk *, unsigned long);
 	void			(*init)(struct clk *);
 	int			(*enable)(struct clk *);
 	void			(*disable)(struct clk *);
+	__u8			enable_bit;
+	__s8			usecount;
+	u8			idlest_bit;
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 	u8			fixed_div;
-	u16			clksel_reg;
 	u32			clksel_mask;
 	const struct clksel	*clksel;
 	struct dpll_data	*dpll_data;
@@ -100,6 +99,7 @@ struct clk {
 		const char		*name;
 		struct clockdomain	*ptr;
 	} clkdm;
+	u16			clksel_reg;
 	s16			prcm_mod;
 #else
 	__u8			rate_offset;
author maintainer
#12 lore raw

PATCH 12/22 OMAP2/3 clock: don't use a barrier after clk_disable()

In reply to Paul Walmsley

clk_disable() previously used an ARM barrier, wmb(), to try to ensure that the hardware write completed before continuing. There are some problems with this approach.

The first problem is that wmb() only ensures that the write leaves the ARM -- not that it actually reaches the endpoint device. In this case, the endpoint device - either the PRM, CM, or SCM - is three interconnects away from the ARM, and the final interconnect is low-speed. And the OCP interconnects will post the write, who knows how long that will take to complete. So the wmb() is not really what we want.

Worse, the wmb() is indiscriminate; it will cause the ARM to flush any other unrelated buffered writes and wait for the local interconnect to acknowledge them - potentially very expensive.

This first problem could be fixed by doing a readback of the same PRM/CM/SCM register. Since these devices use a single OCP thread, this will cause the MPU to wait for the write to complete.

But the primary problem is a conceptual one: clk_disable() should not need any kind of barrier. clk_enable() needs one since device driver code must not access a device until its clocks are known to be enabled. But clk_disable() has no such restriction.

Since blocking the MPU on a PRM/CM/SCM write can be a very high-latency operation - several hundred MPU cycles - it's worth avoiding this barrier if possible.

---
 arch/arm/mach-omap2/clock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/clock.c +1 -1
index 8599b34..d0caeef 100644
@@ -450,7 +450,7 @@ static void _omap2_clk_disable(struct clk *clk)
 	else
 		v &= ~(1 << clk->enable_bit);
 	_omap2_clk_write_reg(v, clk->enable_reg, clk);
-	wmb();
+	/* No OCP barrier needed here since it is a disable operation */
 }
 
 void omap2_clk_disable(struct clk *clk)
author maintainer
#13 lore raw

PATCH 13/22 OMAP2xxx clock: consolidate DELAYED_APP clock commits; fix barrier

In reply to Paul Walmsley

Consolidate the commit code for DELAYED_APP clocks into a subroutine, _omap2xxx_clk_commit(). Also convert the MPU barrier wmb() into an OCP barrier, since with an MPU barrier, we have no guarantee that the write actually reached the endpoint device.

---
 arch/arm/mach-omap2/clock.c |   34 ++++++++++++++++++++++++----------
 1 files changed, 24 insertions(+), 10 deletions(-)
arch/arm/mach-omap2/clock.c +24 -10
index d0caeef..78e14bf 100644
@@ -120,6 +120,28 @@ static void _omap2_clk_write_reg(u32 v, u16 reg_offset, struct clk *clk)
 		cm_write_mod_reg(v, clk->prcm_mod, reg_offset);
 }
 
+/**
+ * _omap2xxx_clk_commit - commit clock parent/rate changes in hardware
+ * @clk: struct clk *
+ *
+ * If @clk has the DELAYED_APP flag set, meaning that parent/rate changes
+ * don't take effect until the VALID_CONFIG bit is written, write the
+ * VALID_CONFIG bit and wait for the write to complete.  No return value.
+ */
+static void _omap2xxx_clk_commit(struct clk *clk)
+{
+	if (!cpu_is_omap24xx())
+		return;
+
+	if (!(clk->flags & DELAYED_APP))
+		return;
+
+	prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD,
+			  OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+	/* OCP barrier */
+	prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+}
+
 /*
  * _dpll_test_fint - test whether an Fint value is valid for the DPLL
  * @clk: DPLL struct clk to test
@@ -757,11 +779,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 
 	clk->rate = clk->parent->rate / new_div;
 
-	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
-		prm_write_mod_reg(OMAP24XX_VALID_CONFIG,
-			OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
-		wmb();
-	}
+	_omap2xxx_clk_commit(clk);
 
 	return 0;
 }
@@ -835,11 +853,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	_omap2_clk_write_reg(v, clk->clksel_reg, clk);
 	wmb();
 
-	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
-		prm_write_mod_reg(OMAP24XX_VALID_CONFIG,
-			OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
-		wmb();
-	}
+	_omap2xxx_clk_commit(clk);
 
 	if (clk->usecount > 0)
 		_omap2_clk_enable(clk);
author maintainer
#14 lore raw

PATCH 14/22 OMAP2/3 clock: convert remaining MPU barriers into OCP barriers

In reply to Paul Walmsley

Several parts of the OMAP2/3 clock code use wmb() to try to ensure that the hardware write completes before continuing. This approach is
problematic: wmb() only ensures that the write leaves the ARM. It does not ensure that the write actually reaches the endpoint device. The endpoint device in this case - either the PRM, CM, or SCM - is three interconnects away from the ARM - and the final interconnect is low-speed. And the OCP interconnects will post the write, and who knows how long that will take to complete. So the wmb() is not what we want. Worse, the wmb() is indiscriminate; it causes the ARM to flush any other unrelated buffered writes and wait for the local interconnect to acknowledge them - potentially very expensive.

Fix this by converting the wmb()s into readbacks of the same PRM/CM/SCM register. Since the PRM/CM/SCM devices use a single OCP thread, this will cause the MPU to block while waiting for posted writes to that device to complete.

---
 arch/arm/mach-omap2/clock.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/clock.c +3 -4
index 78e14bf..0946a5a 100644
@@ -446,7 +446,7 @@ static int _omap2_clk_enable(struct clk *clk)
 	else
 		v |= (1 << clk->enable_bit);
 	_omap2_clk_write_reg(v, clk->enable_reg, clk);
-	wmb();
+	v = _omap2_clk_read_reg(clk->enable_reg, clk); /* OCP barrier */
 
 	omap2_clk_wait_ready(clk);
 
@@ -774,8 +774,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 	v &= ~clk->clksel_mask;
 	v |= field_val << __ffs(clk->clksel_mask);
 	_omap2_clk_write_reg(v, clk->clksel_reg, clk);
-
-	wmb();
+	v = _omap2_clk_read_reg(clk->clksel_reg, clk); /* OCP barrier */
 
 	clk->rate = clk->parent->rate / new_div;
 
@@ -851,7 +850,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	v &= ~clk->clksel_mask;
 	v |= field_val << __ffs(clk->clksel_mask);
 	_omap2_clk_write_reg(v, clk->clksel_reg, clk);
-	wmb();
+	v = _omap2_clk_read_reg(clk->clksel_reg, clk);    /* OCP barrier */
 
 	_omap2xxx_clk_commit(clk);
 
author maintainer
#15 lore raw

PATCH 15/22 OMAP clock: drop clk_get_usecount()

In reply to Paul Walmsley

This function is race-prone and mistakenly conveys the impression to drivers that it is part of the clock interface. Get rid of it: core code that absolutely needs this can just check clk->usecount. Drivers should not use it at all.

---
 arch/arm/mach-omap2/pm-debug.c          |    2 +-
 arch/arm/mach-omap2/pm24xx.c            |    2 +-
 arch/arm/plat-omap/clock.c              |   16 ----------------
 arch/arm/plat-omap/include/mach/clock.h |    1 -
 4 files changed, 2 insertions(+), 19 deletions(-)
arch/arm/mach-omap2/pm-debug.c +1 -1
index 0b5c044..0832e05 100644
@@ -93,7 +93,7 @@ void serial_console_sleep(int enable)
 
 	if (enable) {
 		BUG_ON(serial_console_clock_disabled);
-		if (clk_get_usecount(console_fclk) == 0)
+		if (console_fclk->usecount == 0)
 			return;
 		if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
 			return;
arch/arm/mach-omap2/pm24xx.c +1 -1
index 60ff04f..2798e87 100644
@@ -249,7 +249,7 @@ static int omap2_can_sleep(void)
 		return 0;
 	if (atomic_read(&sleep_block) > 0)
 		return 0;
-	if (clk_get_usecount(osc_ck) > 1)
+	if (osc_ck->usecount > 1)
 		return 0;
 	if (omap_dma_running())
 		return 0;
arch/arm/plat-omap/clock.c +0 -16
index ab3d879..8d43d78 100644
@@ -260,22 +260,6 @@ out:
 }
 EXPORT_SYMBOL(clk_disable);
 
-int clk_get_usecount(struct clk *clk)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (clk == NULL || IS_ERR(clk))
-		return 0;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = clk->usecount;
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_get_usecount);
-
 unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
arch/arm/plat-omap/include/mach/clock.h +0 -1
index 2f1c5cd..f0194bc 100644
@@ -138,7 +138,6 @@ extern void followparent_recalc(struct clk *clk, unsigned long parent_rate,
 				u8 rate_storage);
 extern void clk_allow_idle(struct clk *clk);
 extern void clk_deny_idle(struct clk *clk);
-extern int clk_get_usecount(struct clk *clk);
 extern void clk_enable_init_clocks(void);
 #ifdef CONFIG_CPU_FREQ
 extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
author maintainer
#16 lore raw

PATCH 16/22 OMAP2/3 clock: every clock must have a clkdm

In reply to Paul Walmsley

Every OMAP2/3 clock must now have an assigned clockdomain, so we can remove the checks from clk_enable()/clk_disable().

Ideally we would verify that the clockdomain is present during clk_register(), but this is kind of a pain since OMAP1 doesn't have the clkdm union in its struct clk. In the future we should extend arch_clocks to take architecture-specific clk_register() and clk_unregister() functions to handle this kind of situation.

---
 arch/arm/mach-omap2/clock.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/clock.c +4 -6
index 0946a5a..cdad2ae 100644
@@ -202,6 +202,7 @@ void omap2_init_clk_clkdm(struct clk *clk)
 
 	if (!clk->clkdm.name) {
 		pr_err("clock: %s: missing clockdomain", clk->name);
+		WARN_ON(1);
 		return;
 	}
 
@@ -481,8 +482,7 @@ void omap2_clk_disable(struct clk *clk)
 		_omap2_clk_disable(clk);
 		if (clk->parent)
 			omap2_clk_disable(clk->parent);
-		if (clk->clkdm.ptr)
-			omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
+		omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
 
 	}
 }
@@ -500,14 +500,12 @@ int omap2_clk_enable(struct clk *clk)
 			return ret;
 		}
 
-		if (clk->clkdm.ptr)
-			omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
+		omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
 
 		ret = _omap2_clk_enable(clk);
 
 		if (ret != 0) {
-			if (clk->clkdm.ptr)
-				omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
+			omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
 
 			if (clk->parent) {
 				omap2_clk_disable(clk->parent);
author maintainer
#17 lore raw

PATCH 17/22 OMAP2/3 clock: omap2_clk_enable(): refactor usecount check

In reply to Paul Walmsley

Clean up omap2_clk_enable() by moving most of the function body out of the usecount check. Should result in no functional change.

---
 arch/arm/mach-omap2/clock.c |   31 ++++++++++++++++---------------
 1 files changed, 16 insertions(+), 15 deletions(-)
arch/arm/mach-omap2/clock.c +16 -15
index cdad2ae..ab133b2 100644
@@ -491,26 +491,27 @@ int omap2_clk_enable(struct clk *clk)
 {
 	int ret = 0;
 
-	if (clk->usecount++ == 0) {
-		if (clk->parent)
-			ret = omap2_clk_enable(clk->parent);
+	if (++clk->usecount > 1)
+		return 0;
 
-		if (ret != 0) {
-			clk->usecount--;
-			return ret;
-		}
+	if (clk->parent)
+		ret = omap2_clk_enable(clk->parent);
+
+	if (ret != 0) {
+		clk->usecount--;
+		return ret;
+	}
 
-		omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
+	omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
 
-		ret = _omap2_clk_enable(clk);
+	ret = _omap2_clk_enable(clk);
 
-		if (ret != 0) {
-			omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
+	if (ret != 0) {
+		omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
 
-			if (clk->parent) {
-				omap2_clk_disable(clk->parent);
-				clk->usecount--;
-			}
+		if (clk->parent) {
+			omap2_clk_disable(clk->parent);
+			clk->usecount--;
 		}
 	}
 
author maintainer
#18 lore raw

PATCH 18/22 OMAP2/3 clock: omap2_clk_enable(): fix bugs in clockdomain handling

In reply to Paul Walmsley

omap2_clk_enable() should enable a clock's clockdomain before attempting to enable its parent clock's clockdomain. Similarly, in the unlikely event that the parent clock enable fails, the clockdomain should be disabled.

---
 arch/arm/mach-omap2/clock.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/clock.c +3 -2
index ab133b2..6a4bb39 100644
@@ -494,16 +494,17 @@ int omap2_clk_enable(struct clk *clk)
 	if (++clk->usecount > 1)
 		return 0;
 
+	omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
+
 	if (clk->parent)
 		ret = omap2_clk_enable(clk->parent);
 
 	if (ret != 0) {
 		clk->usecount--;
+		omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
 		return ret;
 	}
 
-	omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
-
 	ret = _omap2_clk_enable(clk);
 
 	if (ret != 0) {
author maintainer
#19 lore raw

PATCH 19/22 OMAP2/3 clock: omap2_clk_enable(): fix usecount decrement bug

In reply to Paul Walmsley

If _omap2_clk_enable() fails, the clock's usecount must be decremented by one no matter whether the clock has a parent or not.

---
 arch/arm/mach-omap2/clock.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/clock.c +2 -4
index 6a4bb39..fc2219d 100644
@@ -508,12 +508,10 @@ int omap2_clk_enable(struct clk *clk)
 	ret = _omap2_clk_enable(clk);
 
 	if (ret != 0) {
+		clk->usecount--;
 		omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
-
-		if (clk->parent) {
+		if (clk->parent)
 			omap2_clk_disable(clk->parent);
-			clk->usecount--;
-		}
 	}
 
 	return ret;
author maintainer
#20 lore raw

PATCH 20/22 OMAP2/3 clock: omap2_clk_enable(): fix logic

In reply to Paul Walmsley

Rearrange the parent clock enable status check code so it actually makes sense. No functional change.

---
 arch/arm/mach-omap2/clock.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/clock.c +10 -7
index fc2219d..c21767a 100644
@@ -489,20 +489,23 @@ void omap2_clk_disable(struct clk *clk)
 
 int omap2_clk_enable(struct clk *clk)
 {
-	int ret = 0;
+	int ret;
 
 	if (++clk->usecount > 1)
 		return 0;
 
 	omap2_clkdm_clk_enable(clk->clkdm.ptr, clk);
 
-	if (clk->parent)
-		ret = omap2_clk_enable(clk->parent);
+	if (clk->parent) {
+		int parent_ret;
 
-	if (ret != 0) {
-		clk->usecount--;
-		omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
-		return ret;
+		parent_ret = omap2_clk_enable(clk->parent);
+
+		if (parent_ret != 0) {
+			clk->usecount--;
+			omap2_clkdm_clk_disable(clk->clkdm.ptr, clk);
+			return parent_ret;
+		}
 	}
 
 	ret = _omap2_clk_enable(clk);
author maintainer
#21 lore raw

PATCH 21/22 OMAP2/3 clock: don't tinker with hardirqs when they are supposed to be disabled

In reply to Paul Walmsley

Clock rate change code executes inside a spinlock with hardirqs disabled. The only code that should be messing around with the hardirq state should be the plat-omap/clock.c code. In the omap2_reprogram_dpllcore() case, this probably just wastes cycles, but in the omap3_core_dpll_m2_set_rate() case, this is a nasty bug.

---
 arch/arm/mach-omap2/clock24xx.c |   12 +++---------
 arch/arm/mach-omap2/clock34xx.c |    2 --
 2 files changed, 3 insertions(+), 11 deletions(-)
arch/arm/mach-omap2/clock24xx.c +3 -9
index 67974d6..65584b7 100644
@@ -220,10 +220,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 	u32 bypass = 0;
 	struct prcm_config tmpset;
 	const struct dpll_data *dd;
-	unsigned long flags;
-	int ret = -EINVAL;
 
-	local_irq_save(flags);
 	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
 	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
@@ -235,7 +232,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 	} else if (rate != cur_rate) {
 		valid_rate = omap2_dpllcore_round_rate(rate);
 		if (valid_rate != rate)
-			goto dpll_exit;
+			return -EINVAL;
 
 		if (mult == 1)
 			low = curr_prcm_set->dpll_speed;
@@ -244,7 +241,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 
 		dd = clk->dpll_data;
 		if (!dd)
-			goto dpll_exit;
+			return -EINVAL;
 
 		tmpset.cm_clksel1_pll = cm_read_mod_reg(clk->prcm_mod,
 							dd->mult_div1_reg);
@@ -282,11 +279,8 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
 		omap2xxx_sdrc_reprogram(done_rate, 0);
 	}
-	ret = 0;
 
-dpll_exit:
-	local_irq_restore(flags);
-	return(ret);
+	return 0;
 }
 
 /**
arch/arm/mach-omap2/clock34xx.c +0 -2
index 917664d..1878282 100644
@@ -491,10 +491,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 	WARN_ON(new_div != 1 && new_div != 2);
 
 	/* REVISIT: Add SDRC_MR changing to this code also */
-	local_irq_disable();
 	omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
 				  sp->actim_ctrlb, new_div);
-	local_irq_enable();
 
 	return 0;
 }
author maintainer
#22 lore raw

PATCH 22/22 OMAP3 SmartReflex: get rid of custom clocks

In reply to Paul Walmsley

smartreflex.c defines some custom clocks that don't have clockdomains associated with them, which is now disallowed. The custom clocks are not actually needed, so remove them. This patch should not cause any functional change.

Cc Kalle Jokiniemi <[email protected]>
---
 arch/arm/mach-omap2/smartreflex.c |   89 ++++++++-----------------------------
 1 files changed, 19 insertions(+), 70 deletions(-)
arch/arm/mach-omap2/smartreflex.c +19 -70
index 9fa033d..f26a9a1 100644
@@ -53,13 +53,6 @@ struct omap_sr {
 	void __iomem	*vpbase_addr;
 };
 
-/* Custom clocks to enable SR specific enable/disable functions. */
-struct sr_custom_clk {
-	struct clk	clk;  /* meta-clock with custom enable/disable calls */
-	struct clk	*fck; /* actual functional clock */
-	struct omap_sr	*sr;
-};
-
 #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
@@ -84,38 +77,28 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
 	return __raw_readl(SR_REGADDR(offset));
 }
 
-/* Custom clock handling functions */
-static int sr_clk_enable(struct clk *clk)
+static int sr_clk_enable(struct omap_sr *sr)
 {
-	struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
-									clk);
-
-	if (clk_enable(sr_clk->fck) != 0) {
-		printk(KERN_ERR "Could not enable %s\n", sr_clk->fck->name);
-		goto clk_enable_err;
+	if (clk_enable(sr->clk) != 0) {
+		printk(KERN_ERR "Could not enable %s\n", sr->clk->name);
+		return -1;
 	}
 
 	/* set fclk- active , iclk- idle */
-	sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
-						SR_CLKACTIVITY_IOFF_FON);
+	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
+		      SR_CLKACTIVITY_IOFF_FON);
 
 	return 0;
-
-clk_enable_err:
-	return -1;
 }
 
-static void sr_clk_disable(struct clk *clk)
+static void sr_clk_disable(struct omap_sr *sr)
 {
-	struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
-									clk);
-
 	/* set fclk, iclk- idle */
-	sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
-						SR_CLKACTIVITY_IOFF_FOFF);
+	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
+		      SR_CLKACTIVITY_IOFF_FOFF);
 
-	clk_disable(sr_clk->fck);
-	sr_clk->sr->is_sr_reset = 1;
+	clk_disable(sr->clk);
+	sr->is_sr_reset = 1;
 }
 
 static struct omap_sr sr1 = {
@@ -134,24 +117,6 @@ static struct omap_sr sr2 = {
 	.srbase_addr		= OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
 };
 
-static struct sr_custom_clk sr1_custom_clk = {
-	.clk = {
-			.name		= "sr1_custom_clk",
-			.enable		= sr_clk_enable,
-			.disable	= sr_clk_disable,
-	},
-	.sr	= &sr1,
-};
-
-static struct sr_custom_clk sr2_custom_clk = {
-	.clk = {
-			.name		= "sr2_custom_clk",
-			.enable		= sr_clk_enable,
-			.disable	= sr_clk_disable,
-	},
-	.sr	= &sr2,
-};
-
 static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
 {
 	u32 gn, rn, mul;
@@ -181,20 +146,6 @@ static u32 cal_test_nvalue(u32 sennval, u32 senpval)
 		(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
 }
 
-static void sr_clk_init(struct sr_custom_clk *sr_clk)
-{
-	if (sr_clk->sr->srid == SR1) {
-		sr_clk->fck = clk_get(NULL, "sr1_fck");
-		if (IS_ERR(sr_clk->fck))
-			printk(KERN_ERR "Could not get sr1_fck\n");
-	} else if (sr_clk->sr->srid == SR2) {
-		sr_clk->fck = clk_get(NULL, "sr2_fck");
-		if (IS_ERR(sr_clk->fck))
-			printk(KERN_ERR "Could not get sr2_fck\n");
-	}
-	clk_register(&sr_clk->clk);
-}
-
 static void sr_set_clk_length(struct omap_sr *sr)
 {
 	struct clk *osc_sys_ck;
@@ -511,7 +462,7 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
 		sr = &sr2;
 
 	if (sr->is_sr_reset == 1) {
-		clk_enable(sr->clk);
+		sr_clk_enable(sr);
 		sr_configure(sr);
 	}
 
@@ -524,7 +475,7 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
 		printk(KERN_WARNING "SR%d: VDD autocomp not activated\n", srid);
 		sr->is_autocomp_active = 0;
 		if (sr->is_sr_reset == 1)
-			clk_disable(sr->clk);
+			sr_clk_disable(sr);
 	}
 }
 EXPORT_SYMBOL(sr_start_vddautocomap);
@@ -540,7 +491,7 @@ int sr_stop_vddautocomap(int srid)
 
 	if (sr->is_autocomp_active == 1) {
 		sr_disable(sr);
-		clk_disable(sr->clk);
+		sr_clk_disable(sr);
 		sr->is_autocomp_active = 0;
 		return SR_TRUE;
 	} else {
@@ -565,7 +516,7 @@ void enable_smartreflex(int srid)
 	if (sr->is_autocomp_active == 1) {
 		if (sr->is_sr_reset == 1) {
 			/* Enable SR clks */
-			clk_enable(sr->clk);
+			sr_clk_enable(sr);
 
 			if (srid == SR1)
 				target_opp_no = get_opp_no(current_vdd1_opp);
@@ -575,7 +526,7 @@ void enable_smartreflex(int srid)
 			sr_configure(sr);
 
 			if (!sr_enable(sr, target_opp_no))
-				clk_disable(sr->clk);
+				sr_clk_disable(sr);
 		}
 	}
 }
@@ -598,7 +549,7 @@ void disable_smartreflex(int srid)
 							~SRCONFIG_SRENABLE);
 
 			/* Disable SR clk */
-			clk_disable(sr->clk);
+			sr_clk_disable(sr);
 			if (sr->srid == SR1) {
 				/* Disable VP1 */
 				prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
@@ -774,10 +725,8 @@ static int __init omap3_sr_init(void)
 		current_vdd2_opp = PRCM_VDD1_OPP1;
 	}
 	if (cpu_is_omap34xx()) {
-		sr_clk_init(&sr1_custom_clk);
-		sr_clk_init(&sr2_custom_clk);
-		sr1.clk = clk_get(NULL, "sr1_custom_clk");
-		sr2.clk = clk_get(NULL, "sr2_custom_clk");
+		sr1.clk = clk_get(NULL, "sr1_fck");
+		sr2.clk = clk_get(NULL, "sr2_fck");
 	}
 	sr_set_clk_length(&sr1);
 	sr_set_clk_length(&sr2);
#24 lore raw
In reply to Paul Walmsley

Hi,

Quoted 1 line

this 22-patch series updates the OMAP1/2/3 clock code. Highlights:

For OMAP3 as long as there is attention, much seems nice. I can't really appreciate with out spending a lot more time.

Is there any way to get more OMAP1/2 testing? It would be nice to not cut off any other upper level users.

There are so many hw & sw bugs and behaviors embedded in clock/power code its hard to make big changes across architectures without large user bases on each one.

Regards,
Richard W.

author maintainer
#25 lore raw

Hello Richard,

Quoted 1 line · Richard

Is there any way to get more OMAP1/2 testing? It would be nice to not cut off any other upper level users.

Any testing, or donations of boards for testing, from OMAP stakeholders is welcomed.

- Paul