linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization
@ 2009-01-28 19:27 Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 01/14] OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h Paul Walmsley
                   ` (13 more replies)
  0 siblings, 14 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap

This series is the fifth of six to bring the mainline kernel OMAP
clock code up-to-date with the linux-omap tree.  This series updates
the SDRAM controller timing code, which is dependent on the clock framework;
and optimizes the clock code.

Some patches have been "compressed" together, as requested by rmk.
Original commit IDs are in the patch descriptions.

Compile-tested on OSK5912 (OMAP1), H4 and 2430SDP (OMAP2), and
BeagleBoard (OMAP3).  Boot-tested on 2430SDP and BeagleBoard.

Applies on top of series D, posted earlier.


- Paul

---

Paul Walmsley (11):
      OMAP clock: unnecessary clock flag removal fiesta
      OMAP clock: track child clocks
      OMAP clock: support "dry run" rate and parent changes
      OMAP2/3 clock: drop recalc function pointers from fixed rate clocks
      OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
      OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init()
      OMAP3 clock: add omap3_core_dpll_m2_set_rate()
      OMAP2 SDRC: add SDRAM timing parameter infrastructure
      OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code
      OMAP2 SDRC: rename memory.c to sdrc2xxx.c
      OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h

Russell King (2):
      OMAP clock: rearrange clock.h structure order
      OMAP2/3 clock: remove clk->owner

Tero Kristo (1):
      PM: OMAP3: Make sure clk_disable_unused() order is correct


 arch/arm/mach-omap1/clock.c              |   87 +++++++----
 arch/arm/mach-omap1/clock.h              |   60 ++++----
 arch/arm/mach-omap2/Makefile             |    6 +
 arch/arm/mach-omap2/board-2430sdp.c      |    2 
 arch/arm/mach-omap2/board-apollon.c      |    2 
 arch/arm/mach-omap2/board-generic.c      |    2 
 arch/arm/mach-omap2/board-h4.c           |    2 
 arch/arm/mach-omap2/board-ldp.c          |    2 
 arch/arm/mach-omap2/board-omap3beagle.c  |    2 
 arch/arm/mach-omap2/clock.c              |   73 ++++-----
 arch/arm/mach-omap2/clock.h              |    8 +
 arch/arm/mach-omap2/clock24xx.c          |  138 +++++++++++------
 arch/arm/mach-omap2/clock24xx.h          |   89 ++++-------
 arch/arm/mach-omap2/clock34xx.c          |  106 +++++++++++--
 arch/arm/mach-omap2/clock34xx.h          |  237 +++++++++++-------------------
 arch/arm/mach-omap2/io.c                 |    8 +
 arch/arm/mach-omap2/memory.c             |  194 -------------------------
 arch/arm/mach-omap2/memory.h             |   43 -----
 arch/arm/mach-omap2/sdrc.c               |   93 ++++++++++++
 arch/arm/mach-omap2/sdrc2xxx.c           |  166 +++++++++++++++++++++
 arch/arm/plat-omap/clock.c               |  229 +++++++++++++++++++++++++----
 arch/arm/plat-omap/common.c              |    2 
 arch/arm/plat-omap/include/mach/clock.h  |   76 ++++++----
 arch/arm/plat-omap/include/mach/common.h |    2 
 arch/arm/plat-omap/include/mach/gpmc.h   |    2 
 arch/arm/plat-omap/include/mach/io.h     |    4 -
 arch/arm/plat-omap/include/mach/sdrc.h   |   64 +++++++-
 27 files changed, 1014 insertions(+), 685 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/memory.c
 delete mode 100644 arch/arm/mach-omap2/memory.h
 create mode 100644 arch/arm/mach-omap2/sdrc.c
 create mode 100644 arch/arm/mach-omap2/sdrc2xxx.c

   text    data     bss     dec     hex filename
3241643  164672  100912 3507227  35841b vmlinux.beagle.old
3241435  165504  100880 3507819  35866b vmlinux.beagle


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH E 01/14] OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 02/14] OMAP2 SDRC: rename memory.c to sdrc2xxx.c Paul Walmsley
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

Move the contents of the arch/arm/mach-omap2/memory.h file to the
existing include/asm-arm/arch-omap/sdrc.h file, and remove memory.h.
Modify files which include memory.h to include asm/arch/sdrc.h instead.

linux-omap source commit is e7ae2d89921372fc4b9712a32cc401d645597807.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/clock.c            |    2 +
 arch/arm/mach-omap2/clock24xx.c        |    2 +
 arch/arm/mach-omap2/clock34xx.c        |    2 +
 arch/arm/mach-omap2/io.c               |    4 +--
 arch/arm/mach-omap2/memory.c           |    9 ++++++-
 arch/arm/mach-omap2/memory.h           |   43 --------------------------------
 arch/arm/plat-omap/include/mach/gpmc.h |    2 +
 arch/arm/plat-omap/include/mach/sdrc.h |   21 ++++++++++++++++
 8 files changed, 35 insertions(+), 50 deletions(-)
 delete mode 100644 arch/arm/mach-omap2/memory.h

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 0cd4761..9c62ada 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -31,7 +31,7 @@
 #include <mach/control.h>
 #include <asm/div64.h>
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "sdrc.h"
 #include "clock.h"
 #include "prm.h"
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index e66287f..a11ba09 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -34,7 +34,7 @@
 
 #include <asm/div64.h>
 
-#include "memory.h"
+#include <asm/arch/sdrc.h>
 #include "clock.h"
 #include "clock24xx.h"
 #include "prm.h"
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index c3c8537..3dba9ca 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -31,7 +31,7 @@
 #include <mach/sram.h>
 #include <asm/div64.h>
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "clock.h"
 #include "clock34xx.h"
 #include "prm.h"
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 5ea64f9..2b5f28a 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -27,8 +27,8 @@
 #include <mach/mux.h>
 #include <mach/omapfb.h>
 #include <mach/sram.h>
-
-#include "memory.h"
+#include <mach/sdrc.h>
+#include <mach/gpmc.h>
 
 #include "clock.h"
 
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
index db024fd..62a87cf 100644
--- a/arch/arm/mach-omap2/memory.c
+++ b/arch/arm/mach-omap2/memory.c
@@ -31,9 +31,16 @@
 
 #include "clock.h"
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "sdrc.h"
 
+/* Memory timing, DLL mode flags */
+#define M_DDR		1
+#define M_LOCK_CTRL	(1 << 2)
+#define M_UNLOCK	0
+#define M_LOCK		1
+
+
 void __iomem *omap2_sdrc_base;
 void __iomem *omap2_sms_base;
 
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
deleted file mode 100644
index bb3db80..0000000
--- a/arch/arm/mach-omap2/memory.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/memory.h
- *
- * Interface for memory timing related functions for OMAP24XX
- *
- * Copyright (C) 2005 Texas Instruments Inc.
- * Richard Woodruff <r-woodruff2@ti.com>
- *
- * Copyright (C) 2005 Nokia Corporation
- * Tony Lindgren <tony@atomide.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef ARCH_ARM_MACH_OMAP2_MEMORY_H
-#define ARCH_ARM_MACH_OMAP2_MEMORY_H
-
-/* Memory timings */
-#define M_DDR		1
-#define M_LOCK_CTRL	(1 << 2)
-#define M_UNLOCK	0
-#define M_LOCK		1
-
-struct memory_timings {
-	u32 m_type;		/* ddr = 1, sdr = 0 */
-	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
-	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
-	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
-	u32 base_cs;		/* base chip select to use for calculations */
-};
-
-extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
-extern u32 omap2_memory_get_slow_dll_ctrl(void);
-extern u32 omap2_memory_get_fast_dll_ctrl(void);
-extern u32 omap2_memory_get_type(void);
-u32 omap2_dll_force_needed(void);
-u32 omap2_reprogram_sdrc(u32 level, u32 force);
-void __init omap2_init_memory(void);
-void __init gpmc_init(void);
-
-#endif
diff --git a/arch/arm/plat-omap/include/mach/gpmc.h b/arch/arm/plat-omap/include/mach/gpmc.h
index 45b6784..921b165 100644
--- a/arch/arm/plat-omap/include/mach/gpmc.h
+++ b/arch/arm/plat-omap/include/mach/gpmc.h
@@ -103,6 +103,6 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
-extern void gpmc_init(void);
+extern void __init gpmc_init(void);
 
 #endif
diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
index a98c6c3..c905b52 100644
--- a/arch/arm/plat-omap/include/mach/sdrc.h
+++ b/arch/arm/plat-omap/include/mach/sdrc.h
@@ -74,4 +74,25 @@
 #define SMS_SYSCONFIG		0x010
 /* REVISIT: fill in other SMS registers here */
 
+#ifndef __ASSEMBLER__
+
+struct memory_timings {
+	u32 m_type;		/* ddr = 1, sdr = 0 */
+	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
+	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
+	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
+	u32 base_cs;		/* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
+u32 omap2_dll_force_needed(void);
+u32 omap2_reprogram_sdrc(u32 level, u32 force);
+void __init omap2_init_memory(void);
+
+#endif
+
+
 #endif



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 02/14] OMAP2 SDRC: rename memory.c to sdrc2xxx.c
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 01/14] OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 03/14] OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code Paul Walmsley
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

Rename arch/arm/mach-omap2/memory.c to arch/arm/mach-omap2/sdrc2xxx.c, since
it contains exclusively SDRAM-related functions.  Most of the functions
are also OMAP2xxx-specific - those which are common will be separated out
in a following patch.

linux-omap source commit is fe212f797e2efef9dc88bcb5db7cf9db3f9f562e.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/Makefile   |    2 +-
 arch/arm/mach-omap2/sdrc2xxx.c |   16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)
 rename arch/arm/mach-omap2/{memory.c => sdrc2xxx.c} (95%)

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index bbd12bc..bb47d43 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \
+obj-y := irq.o id.o io.o sdrc2xxx.o control.o prcm.o clock.o mux.o \
 		devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
 		clockdomain.o
 
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/sdrc2xxx.c
similarity index 95%
rename from arch/arm/mach-omap2/memory.c
rename to arch/arm/mach-omap2/sdrc2xxx.c
index 62a87cf..c636228 100644
--- a/arch/arm/mach-omap2/memory.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -1,7 +1,7 @@
 /*
- * linux/arch/arm/mach-omap2/memory.c
+ * linux/arch/arm/mach-omap2/sdrc2xxx.c
  *
- * Memory timing related functions for OMAP24XX
+ * SDRAM timing related functions for OMAP2xxx
  *
  * Copyright (C) 2005 Texas Instruments Inc.
  * Richard Woodruff <r-woodruff2@ti.com>
@@ -91,19 +91,18 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force)
 	if ((curr_perf_level == level) && !force)
 		return prev;
 
-	if (level == CORE_CLK_SRC_DPLL) {
+	if (level == CORE_CLK_SRC_DPLL)
 		dll_ctrl = omap2_memory_get_slow_dll_ctrl();
-	} else if (level == CORE_CLK_SRC_DPLL_X2) {
+	else if (level == CORE_CLK_SRC_DPLL_X2)
 		dll_ctrl = omap2_memory_get_fast_dll_ctrl();
-	} else {
+	else
 		return prev;
-	}
 
 	m_type = omap2_memory_get_type();
 
 	local_irq_save(flags);
 	prm_write_mod_reg(0xffff, OMAP24XX_GR_MOD,
-					OMAP24XX_PRCM_VOLTSETUP_OFFSET);
+			  OMAP24XX_PRCM_VOLTSETUP_OFFSET);
 	omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type);
 	curr_perf_level = level;
 	local_irq_restore(flags);
@@ -127,7 +126,8 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
 	unsigned long dll_cnt;
 	u32 fast_dll = 0;
 
-	mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+	/* DDR = 1, SDR = 0 */
+	mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1);
 
 	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
 	 * In the case of 2422, its ok to use CS1 instead of CS0.



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 03/14] OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 01/14] OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 02/14] OMAP2 SDRC: rename memory.c to sdrc2xxx.c Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 04/14] OMAP2 SDRC: add SDRAM timing parameter infrastructure Paul Walmsley
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

Separate SDRC code common to OMAP2/3 from mach-omap2/sdrc2xxx.c to
mach-omap2/sdrc.c.  Rename the OMAP2xxx-specific functions to use an
'omap2xxx' prefix rather than an 'omap2' prefix, and use "sdrc" in the
function names rather than "memory."  Mark several functions
as static that should not be used outside the sdrc2xxx.c file.

linux-omap source commit is bf1612b9d8d29379558500cd5de9ae0367c41fc4.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/Makefile             |    6 ++-
 arch/arm/mach-omap2/clock24xx.c          |   25 ++++++-----
 arch/arm/mach-omap2/io.c                 |    2 -
 arch/arm/mach-omap2/sdrc.c               |   57 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/sdrc2xxx.c           |   67 +++++++-----------------------
 arch/arm/plat-omap/common.c              |    2 -
 arch/arm/plat-omap/include/mach/common.h |    2 -
 arch/arm/plat-omap/include/mach/sdrc.h   |   37 ++++++++++-------
 8 files changed, 116 insertions(+), 82 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sdrc.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index bb47d43..9717afc 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o sdrc2xxx.o control.o prcm.o clock.o mux.o \
+obj-y := irq.o id.o io.o sdrc.o control.o prcm.o clock.o mux.o \
 		devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
 		clockdomain.o
 
@@ -14,6 +14,10 @@ obj-$(CONFIG_ARCH_OMAP2420)		+= sram242x.o
 obj-$(CONFIG_ARCH_OMAP2430)		+= sram243x.o
 obj-$(CONFIG_ARCH_OMAP3)		+= sram34xx.o
 
+# SMS/SDRC
+obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
+# obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
+
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-y					+= pm.o
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index a11ba09..640a2cb 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -34,7 +34,7 @@
 
 #include <asm/div64.h>
 
-#include <asm/arch/sdrc.h>
+#include <mach/sdrc.h>
 #include "clock.h"
 #include "clock24xx.h"
 #include "prm.h"
@@ -198,9 +198,9 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
 	if ((rate == (cur_rate / 2)) && (mult == 2)) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
 	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 	} else if (rate != cur_rate) {
 		valid_rate = omap2_dpllcore_round_rate(rate);
 		if (valid_rate != rate)
@@ -240,15 +240,16 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
 			bypass = 1;
 
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
+		/* For omap2xxx_sdrc_init_params() */
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 
 		/* Force dll lock mode */
 		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
 			       bypass);
 
 		/* Errata: ret dll entry state */
-		omap2_init_memory_params(omap2_dll_force_needed());
-		omap2_reprogram_sdrc(done_rate, 0);
+		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+		omap2xxx_sdrc_reprogram(done_rate, 0);
 	}
 	omap2_dpllcore_recalc(&dpll_ck);
 	ret = 0;
@@ -335,9 +336,9 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
 
 	if (prcm->dpll_speed == cur_rate / 2) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
 	} else if (prcm->dpll_speed == cur_rate * 2) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 	} else if (prcm->dpll_speed != cur_rate) {
 		local_irq_save(flags);
 
@@ -368,14 +369,14 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 			cm_write_mod_reg(prcm->cm_clksel_mdm,
 					 OMAP2430_MDM_MOD, CM_CLKSEL);
 
-		/* x2 to enter init_mem */
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		/* x2 to enter omap2xxx_sdrc_init_params() */
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 
 		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
 			       bypass);
 
-		omap2_init_memory_params(omap2_dll_force_needed());
-		omap2_reprogram_sdrc(done_rate, 0);
+		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+		omap2xxx_sdrc_reprogram(done_rate, 0);
 
 		local_irq_restore(flags);
 	}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 2b5f28a..3c1de36 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -201,6 +201,6 @@ void __init omap2_init_common_hw(void)
 	pwrdm_init(powerdomains_omap);
 	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
 	omap2_clk_init();
-	omap2_init_memory();
+	omap2_sdrc_init();
 	gpmc_init();
 }
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
new file mode 100644
index 0000000..24b54d5
--- /dev/null
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -0,0 +1,57 @@
+/*
+ * SMS/SDRC (SDRAM controller) common code for OMAP2/3
+ *
+ * Copyright (C) 2005, 2008 Texas Instruments Inc.
+ * Copyright (C) 2005, 2008 Nokia Corporation
+ *
+ * Tony Lindgren <tony@atomide.com>
+ * Paul Walmsley
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/sram.h>
+
+#include "prm.h"
+
+#include <mach/sdrc.h>
+#include "sdrc.h"
+
+void __iomem *omap2_sdrc_base;
+void __iomem *omap2_sms_base;
+
+void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
+{
+	omap2_sdrc_base = omap2_globals->sdrc;
+	omap2_sms_base = omap2_globals->sms;
+}
+
+/* turn on smart idle modes for SDRAM scheduler and controller */
+void __init omap2_sdrc_init(void)
+{
+	u32 l;
+
+	l = sms_read_reg(SMS_SYSCONFIG);
+	l &= ~(0x3 << 3);
+	l |= (0x2 << 3);
+	sms_write_reg(l, SMS_SYSCONFIG);
+
+	l = sdrc_read_reg(SDRC_SYSCONFIG);
+	l &= ~(0x3 << 3);
+	l |= (0x2 << 3);
+	sdrc_write_reg(l, SDRC_SYSCONFIG);
+}
diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c
index c636228..130e7b7 100644
--- a/arch/arm/mach-omap2/sdrc2xxx.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -3,11 +3,12 @@
  *
  * SDRAM timing related functions for OMAP2xxx
  *
- * Copyright (C) 2005 Texas Instruments Inc.
- * Richard Woodruff <r-woodruff2@ti.com>
+ * Copyright (C) 2005, 2008 Texas Instruments Inc.
+ * Copyright (C) 2005, 2008 Nokia Corporation
  *
- * Copyright (C) 2005 Nokia Corporation
  * Tony Lindgren <tony@atomide.com>
+ * Paul Walmsley
+ * Richard Woodruff <r-woodruff2@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -41,23 +42,20 @@
 #define M_LOCK		1
 
 
-void __iomem *omap2_sdrc_base;
-void __iomem *omap2_sms_base;
-
 static struct memory_timings mem_timings;
 static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
 
-u32 omap2_memory_get_slow_dll_ctrl(void)
+static u32 omap2xxx_sdrc_get_slow_dll_ctrl(void)
 {
 	return mem_timings.slow_dll_ctrl;
 }
 
-u32 omap2_memory_get_fast_dll_ctrl(void)
+static u32 omap2xxx_sdrc_get_fast_dll_ctrl(void)
 {
 	return mem_timings.fast_dll_ctrl;
 }
 
-u32 omap2_memory_get_type(void)
+static u32 omap2xxx_sdrc_get_type(void)
 {
 	return mem_timings.m_type;
 }
@@ -66,7 +64,7 @@ u32 omap2_memory_get_type(void)
  * Check the DLL lock state, and return tue if running in unlock mode.
  * This is needed to compensate for the shifted DLL value in unlock mode.
  */
-u32 omap2_dll_force_needed(void)
+u32 omap2xxx_sdrc_dll_is_unlocked(void)
 {
 	/* dlla and dllb are a set */
 	u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL);
@@ -81,8 +79,10 @@ u32 omap2_dll_force_needed(void)
  * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC.
  * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or
  * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2)
+ *
+ * Used by the clock framework during CORE DPLL changes
  */
-u32 omap2_reprogram_sdrc(u32 level, u32 force)
+u32 omap2xxx_sdrc_reprogram(u32 level, u32 force)
 {
 	u32 dll_ctrl, m_type;
 	u32 prev = curr_perf_level;
@@ -92,13 +92,13 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force)
 		return prev;
 
 	if (level == CORE_CLK_SRC_DPLL)
-		dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+		dll_ctrl = omap2xxx_sdrc_get_slow_dll_ctrl();
 	else if (level == CORE_CLK_SRC_DPLL_X2)
-		dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+		dll_ctrl = omap2xxx_sdrc_get_fast_dll_ctrl();
 	else
 		return prev;
 
-	m_type = omap2_memory_get_type();
+	m_type = omap2xxx_sdrc_get_type();
 
 	local_irq_save(flags);
 	prm_write_mod_reg(0xffff, OMAP24XX_GR_MOD,
@@ -110,18 +110,8 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force)
 	return prev;
 }
 
-#if !defined(CONFIG_ARCH_OMAP2)
-void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-				u32 base_cs, u32 force_unlock)
-{
-}
-void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
-				      u32 mem_type)
-{
-}
-#endif
-
-void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+/* Used by the clock framework during CORE DPLL changes */
+void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode)
 {
 	unsigned long dll_cnt;
 	u32 fast_dll = 0;
@@ -174,28 +164,3 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
 	/* 90 degree phase for anything below 133Mhz + disable DLL filter */
 	mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
 }
-
-void __init omap2_set_globals_memory(struct omap_globals *omap2_globals)
-{
-	omap2_sdrc_base = omap2_globals->sdrc;
-	omap2_sms_base = omap2_globals->sms;
-}
-
-/* turn on smart idle modes for SDRAM scheduler and controller */
-void __init omap2_init_memory(void)
-{
-	u32 l;
-
-	if (!cpu_is_omap2420())
-		return;
-
-	l = sms_read_reg(SMS_SYSCONFIG);
-	l &= ~(0x3 << 3);
-	l |= (0x2 << 3);
-	sms_write_reg(l, SMS_SYSCONFIG);
-
-	l = sdrc_read_reg(SDRC_SYSCONFIG);
-	l &= ~(0x3 << 3);
-	l |= (0x2 << 3);
-	sdrc_write_reg(l, SDRC_SYSCONFIG);
-}
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 0843b88..187239c 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -249,7 +249,7 @@ static struct omap_globals *omap2_globals;
 static void __init __omap2_set_globals(void)
 {
 	omap2_set_globals_tap(omap2_globals);
-	omap2_set_globals_memory(omap2_globals);
+	omap2_set_globals_sdrc(omap2_globals);
 	omap2_set_globals_control(omap2_globals);
 	omap2_set_globals_prcm(omap2_globals);
 }
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h
index 4ddb661..5f46249 100644
--- a/arch/arm/plat-omap/include/mach/common.h
+++ b/arch/arm/plat-omap/include/mach/common.h
@@ -65,7 +65,7 @@ void omap2_set_globals_343x(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
 void omap2_set_globals_tap(struct omap_globals *);
-void omap2_set_globals_memory(struct omap_globals *);
+void omap2_set_globals_sdrc(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 #ifdef CONFIG_ARCH_OMAP24XX
diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
index c905b52..8e0740e 100644
--- a/arch/arm/plat-omap/include/mach/sdrc.h
+++ b/arch/arm/plat-omap/include/mach/sdrc.h
@@ -4,10 +4,12 @@
 /*
  * OMAP2/3 SDRC/SMS register definitions
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
  *
- * Written by Paul Walmsley
+ * Tony Lindgren
+ * Paul Walmsley
+ * Richard Woodruff
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -64,18 +66,25 @@
  * SMS register access
  */
 
-
-#define OMAP242X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP2420_SMS_BASE + reg)
-#define OMAP243X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP243X_SMS_BASE + reg)
-#define OMAP343X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP343X_SMS_BASE + reg)
+#define OMAP242X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg)
+#define OMAP243X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg)
+#define OMAP343X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg)
 
 /* SMS register offsets - read/write with sms_{read,write}_reg() */
 
 #define SMS_SYSCONFIG		0x010
 /* REVISIT: fill in other SMS registers here */
 
+
 #ifndef __ASSEMBLER__
 
+void __init omap2_sdrc_init(void);
+
+#ifdef CONFIG_ARCH_OMAP2
+
 struct memory_timings {
 	u32 m_type;		/* ddr = 1, sdr = 0 */
 	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
@@ -84,15 +93,13 @@ struct memory_timings {
 	u32 base_cs;		/* base chip select to use for calculations */
 };
 
-extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
-extern u32 omap2_memory_get_slow_dll_ctrl(void);
-extern u32 omap2_memory_get_fast_dll_ctrl(void);
-extern u32 omap2_memory_get_type(void);
-u32 omap2_dll_force_needed(void);
-u32 omap2_reprogram_sdrc(u32 level, u32 force);
-void __init omap2_init_memory(void);
+extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
 
-#endif
+u32 omap2xxx_sdrc_dll_is_unlocked(void);
+u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
+
+#endif  /* CONFIG_ARCH_OMAP2 */
 
+#endif  /* __ASSEMBLER__ */
 
 #endif



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 04/14] OMAP2 SDRC: add SDRAM timing parameter infrastructure
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (2 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 03/14] OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 05/14] OMAP3 clock: add omap3_core_dpll_m2_set_rate() Paul Walmsley
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

For a given SDRAM clock rate, SDRAM chips require memory controllers
to use a specific set of timing minimums and maximums to transfer data
reliably.  These parameters can be different for different memory chips
and can also potentially vary by board.

This patch adds the infrastructure for board-*.c files to pass this
timing data to the SDRAM controller init function.  The timing data is
specified in an 'omap_sdrc_params' structure, in terms of SDRC
controller register values.  An array of these structs, one per SDRC
target clock rate, is passed by the board-*.c file to
omap2_init_common_hw().

This patch does not define the values for different memory chips, nor
does it use the values for anything; those will come in subsequent patches.

linux-omap source commit is bc84ecfc795c2d1c5cda8da4127cf972f488a696.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-2430sdp.c     |    2 +-
 arch/arm/mach-omap2/board-apollon.c     |    2 +-
 arch/arm/mach-omap2/board-generic.c     |    2 +-
 arch/arm/mach-omap2/board-h4.c          |    2 +-
 arch/arm/mach-omap2/board-ldp.c         |    2 +-
 arch/arm/mach-omap2/board-omap3beagle.c |    2 +-
 arch/arm/mach-omap2/io.c                |    4 ++-
 arch/arm/mach-omap2/sdrc.c              |   38 ++++++++++++++++++++++++++++++-
 arch/arm/plat-omap/include/mach/io.h    |    4 ++-
 arch/arm/plat-omap/include/mach/sdrc.h  |   24 +++++++++++++++++++-
 10 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 83fa372..7b29e1d 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -185,7 +185,7 @@ out:
 
 static void __init omap_2430sdp_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	sdp2430_init_smc91x();
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 0a7b24b..0c911f4 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -249,7 +249,7 @@ out:
 
 static void __init omap_apollon_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	apollon_init_smc91x();
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 3b34c20..3492162 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -33,7 +33,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 }
 
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 5e9b146..ef55b45 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -363,7 +363,7 @@ static void __init h4_init_flash(void)
 
 static void __init omap_h4_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	h4_init_flash();
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index f6a1345..61f7c36 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -98,7 +98,7 @@ static inline void __init ldp_init_smc911x(void)
 
 static void __init omap_ldp_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	ldp_init_smc911x();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 38c88fb..ad312cc 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -184,7 +184,7 @@ static int __init omap3_beagle_i2c_init(void)
 
 static void __init omap3_beagle_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 }
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 3c1de36..916fcd3 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -195,12 +195,12 @@ void __init omap2_map_common_io(void)
 	omapfb_reserve_sdram();
 }
 
-void __init omap2_init_common_hw(void)
+void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
 {
 	omap2_mux_init();
 	pwrdm_init(powerdomains_omap);
 	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
 	omap2_clk_init();
-	omap2_sdrc_init();
+	omap2_sdrc_init(sp);
 	gpmc_init();
 }
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index 24b54d5..2a30060 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -12,6 +12,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#undef DEBUG
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -31,9 +32,42 @@
 #include <mach/sdrc.h>
 #include "sdrc.h"
 
+static struct omap_sdrc_params *sdrc_init_params;
+
 void __iomem *omap2_sdrc_base;
 void __iomem *omap2_sms_base;
 
+
+/**
+ * omap2_sdrc_get_params - return SDRC register values for a given clock rate
+ * @r: SDRC clock rate (in Hz)
+ *
+ * Return pre-calculated values for the SDRC_ACTIM_CTRLA,
+ * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given
+ * SDRC clock rate 'r'.  These parameters control various timing
+ * delays in the SDRAM controller that are expressed in terms of the
+ * number of SDRC clock cycles to wait; hence the clock rate
+ * dependency. Note that sdrc_init_params must be sorted rate
+ * descending.  Also assumes that both chip-selects use the same
+ * timing parameters.  Returns a struct omap_sdrc_params * upon
+ * success, or NULL upon failure.
+ */
+struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
+{
+	struct omap_sdrc_params *sp;
+
+	sp = sdrc_init_params;
+
+	while (sp->rate != r)
+		sp++;
+
+	if (!sp->rate)
+		return NULL;
+
+	return sp;
+}
+
+
 void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 {
 	omap2_sdrc_base = omap2_globals->sdrc;
@@ -41,7 +75,7 @@ void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 }
 
 /* turn on smart idle modes for SDRAM scheduler and controller */
-void __init omap2_sdrc_init(void)
+void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
 {
 	u32 l;
 
@@ -54,4 +88,6 @@ void __init omap2_sdrc_init(void)
 	l &= ~(0x3 << 3);
 	l |= (0x2 << 3);
 	sdrc_write_reg(l, SDRC_SYSCONFIG);
+
+	sdrc_init_params = sp;
 }
diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h
index d92bf79..0610d7e 100644
--- a/arch/arm/plat-omap/include/mach/io.h
+++ b/arch/arm/plat-omap/include/mach/io.h
@@ -185,11 +185,13 @@
 #define omap_writew(v,a)	__raw_writew(v, IO_ADDRESS(a))
 #define omap_writel(v,a)	__raw_writel(v, IO_ADDRESS(a))
 
+struct omap_sdrc_params;
+
 extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
 
 extern void omap2_map_common_io(void);
-extern void omap2_init_common_hw(void);
+extern void omap2_init_common_hw(struct omap_sdrc_params *sp);
 
 #define __arch_ioremap(p,s,t)	omap_ioremap(p,s,t)
 #define __arch_iounmap(v)	omap_iounmap(v)
diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
index 8e0740e..adc7352 100644
--- a/arch/arm/plat-omap/include/mach/sdrc.h
+++ b/arch/arm/plat-omap/include/mach/sdrc.h
@@ -81,7 +81,29 @@
 
 #ifndef __ASSEMBLER__
 
-void __init omap2_sdrc_init(void);
+/**
+ * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate
+ * @rate: SDRC clock rate (in Hz)
+ * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate
+ * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate
+ * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate
+ * @mr: Value to program to SDRC_MR for this rate
+ *
+ * This structure holds a pre-computed set of register values for the
+ * SDRC for a given SDRC clock rate and SDRAM chip.  These are
+ * intended to be pre-computed and specified in an array in the board-*.c
+ * files.  The structure is keyed off the 'rate' field.
+ */
+struct omap_sdrc_params {
+	unsigned long rate;
+	u32 actim_ctrla;
+	u32 actim_ctrlb;
+	u32 rfr_ctrl;
+	u32 mr;
+};
+
+void __init omap2_sdrc_init(struct omap_sdrc_params *sp);
+struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r);
 
 #ifdef CONFIG_ARCH_OMAP2
 



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 05/14] OMAP3 clock: add omap3_core_dpll_m2_set_rate()
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (3 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 04/14] OMAP2 SDRC: add SDRAM timing parameter infrastructure Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 06/14] PM: OMAP3: Make sure clk_disable_unused() order is correct Paul Walmsley
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

Add the omap3_core_dpll_m2_set_rate() function to the OMAP3 clock code,
which calls into the SRAM function omap3_sram_configure_core_dpll() to
change the CORE DPLL M2 divider.  (SRAM code is necessary since rate changes
on clocks upstream from the SDRC can glitch SDRAM accesses.)

Use this function for the set_rate function pointer in the dpll3_m2_ck
struct clk.  With this function in place, PM/OPP code should be able to
alter SDRAM speed via code similar to:

      clk_set_rate(&dpll3_m2_ck, target_rate).

linux-omap source commit is 7f8b2b0f4fe52238c67d79dedcd2794dcef4dddd.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/clock34xx.c |   65 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/clock34xx.h |    9 ++---
 2 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 3dba9ca..2c655be 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -434,6 +434,71 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
+
+/*
+ * CORE DPLL (DPLL3) rate programming functions
+ *
+ * These call into SRAM code to do the actual CM writes, since the SDRAM
+ * is clocked from DPLL3.
+ */
+
+/**
+ * omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider
+ * @clk: struct clk * of DPLL to set
+ * @rate: rounded target rate
+ *
+ * Program the DPLL M2 divider with the rounded target rate.  Returns
+ * -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 new_div = 0;
+	unsigned long validrate, sdrcrate;
+	struct omap_sdrc_params *sp;
+
+	if (!clk || !rate)
+		return -EINVAL;
+
+	if (clk != &dpll3_m2_ck)
+		return -EINVAL;
+
+	if (rate == clk->rate)
+		return 0;
+
+	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+	if (validrate != rate)
+		return -EINVAL;
+
+	sdrcrate = sdrc_ick.rate;
+	if (rate > clk->rate)
+		sdrcrate <<= ((rate / clk->rate) - 1);
+	else
+		sdrcrate >>= ((clk->rate / rate) - 1);
+
+	sp = omap2_sdrc_get_params(sdrcrate);
+	if (!sp)
+		return -EINVAL;
+
+	pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
+		validrate);
+	pr_info("clock: SDRC timing params used: %08x %08x %08x\n",
+		sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
+
+	/* REVISIT: SRAM code doesn't support other M2 divisors yet */
+	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();
+
+	omap2_clksel_recalc(clk);
+
+	return 0;
+}
+
+
 /* DPLL autoidle read/set code */
 
 
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 70a1532..5357507 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -35,6 +35,7 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk);
 static int omap3_noncore_dpll_enable(struct clk *clk);
 static void omap3_noncore_dpll_disable(struct clk *clk);
 static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
+static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
 
 /* Maximum DPLL multiplier, divider values for OMAP3 */
 #define OMAP3_MAX_DPLL_MULT		2048
@@ -499,11 +500,7 @@ static const struct clksel div31_dpll3m2_clksel[] = {
 	{ .parent = NULL }
 };
 
-/*
- * DPLL3 output M2
- * REVISIT: This DPLL output divider must be changed in SRAM, so until
- * that code is ready, this should remain a 'read-only' clksel clock.
- */
+/* DPLL3 output M2 - primary control point for CORE speed */
 static struct clk dpll3_m2_ck = {
 	.name		= "dpll3_m2_ck",
 	.parent		= &dpll3_ck,
@@ -515,6 +512,8 @@ static struct clk dpll3_m2_ck = {
 	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap3_core_dpll_m2_set_rate,
 	.recalc		= &omap2_clksel_recalc,
 };
 



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 06/14] PM: OMAP3: Make sure clk_disable_unused() order is correct
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (4 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 05/14] OMAP3 clock: add omap3_core_dpll_m2_set_rate() Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 07/14] OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init() Paul Walmsley
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Tero Kristo, Kevin Hilman

From: Tero Kristo <tero.kristo@nokia.com>

Current implementation will disable clocks in the order defined in clock34xx.h,
at least DPLL4_M2X2 will hang in certain cases (and prevent retention / off)
if clocks are not disabled in correct order. This patch makes sure the parent
clocks will be active when disabling a clock.

linux-omap source commit is 672680063420ef8c8c4e7271984bb9cc08171d29.

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/clock.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 9c62ada..d4d2e7b 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -1078,6 +1078,10 @@ void omap2_clk_disable_unused(struct clk *clk)
 		return;
 
 	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
-	_omap2_clk_disable(clk);
+	if (cpu_is_omap34xx()) {
+		omap2_clk_enable(clk);
+		omap2_clk_disable(clk);
+	} else
+		_omap2_clk_disable(clk);
 }
 #endif



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 07/14] OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init()
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (5 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 06/14] PM: OMAP3: Make sure clk_disable_unused() order is correct Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c Paul Walmsley
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

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().

linux-omap source commit is 03c03330017eeb445b01957608ff5db49a7151b6.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/clock24xx.c |    2 +-
 arch/arm/mach-omap2/clock34xx.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 640a2cb..3727a73 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -502,7 +502,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();
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 2c655be..738a029 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -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
 



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (6 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 07/14] OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init() Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-29 17:41   ` Russell King - ARM Linux
  2009-01-28 19:27 ` [PATCH E 09/14] OMAP2/3 clock: drop recalc function pointers from fixed rate clocks Paul Walmsley
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

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.

linux-omap source commit is b66c1baa9f8e60213457414976575e6265217a70.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 4d0c444..ae2b304 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -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;
 }
 
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index d4d2e7b..4a72535 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -300,9 +300,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);
 }
 
 /**
@@ -504,9 +501,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);
 }
 
 /**
@@ -777,9 +771,6 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
 	if (clk->set_rate)
 		ret = clk->set_rate(clk, rate);
 
-	if (ret == 0 && (clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
-
 	return ret;
 }
 
@@ -861,9 +852,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;
 }
 
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 3727a73..57cd85b 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -179,8 +179,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)
@@ -251,7 +249,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:
@@ -380,7 +377,6 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
 		local_irq_restore(flags);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
 
 	return 0;
 }
@@ -470,13 +466,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);
 }
 
 /*
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 738a029..22cbcce 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -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 */
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index be6aab9..c60548a 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -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);
+		}
 	}
 }
 



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 09/14] OMAP2/3 clock: drop recalc function pointers from fixed rate clocks
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (7 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-28 19:27 ` [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes Paul Walmsley
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

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.

linux-omap source commit is 5e96093d1f7f2ff27ba61f4174f429ddca15a4b9.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 929a257..30f3c57 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -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,
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 5357507..66cbe0c 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -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 */
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index c60548a..4cf1145 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -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);
 		}



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (8 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 09/14] OMAP2/3 clock: drop recalc function pointers from fixed rate clocks Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-02-08 13:17   ` Russell King - ARM Linux
  2009-02-08 15:53   ` Russell King - ARM Linux
  2009-01-28 19:27 ` [PATCH E 11/14] OMAP clock: track child clocks Paul Walmsley
                   ` (3 subsequent siblings)
  13 siblings, 2 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

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.

linux-omap source commit is 33d000c99ee393fe2042f93e8422f94976d276ce.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index ae2b304..f3cf6f8 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -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,
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 43f6ce8..df94ad6 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -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);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 4a72535..0c00706 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -240,6 +240,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
@@ -251,7 +252,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;
@@ -269,7 +270,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()) {
 
@@ -285,7 +286,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;
@@ -295,11 +296,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;
 }
 
 /**
@@ -486,9 +495,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);
 
@@ -496,9 +507,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);
 }
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index faff95e..a026ec9 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -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);
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 57cd85b..cd9fa0d 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -64,6 +64,7 @@ static struct clk *sclk;
 /**
  * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
  * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
+ * @parent_rate: rate of the parent of the dpll_ck
  *
  * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
  * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
@@ -71,12 +72,13 @@ static struct clk *sclk;
  * struct clk *dpll_ck, which is a composite clock of dpll_ck and
  * core_ck.
  */
-static u32 omap2xxx_clk_get_core_rate(struct clk *clk)
+static u32 omap2xxx_clk_get_core_rate(struct clk *clk,
+				      unsigned long parent_rate)
 {
 	long long core_clk;
 	u32 v;
 
-	core_clk = omap2_get_dpll_rate(clk);
+	core_clk = omap2_get_dpll_rate(clk, parent_rate);
 
 	v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	v &= OMAP24XX_CORE_CLK_SRC_MASK;
@@ -89,6 +91,30 @@ static u32 omap2xxx_clk_get_core_rate(struct clk *clk)
 	return core_clk;
 }
 
+static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed,
+							 struct prcm_config **prcm)
+{
+	unsigned long found_speed = 0;
+	struct prcm_config *p;
+
+	p = *prcm;
+
+	for (p = rate_table; p->mpu_speed; p++) {
+		if (!(p->flags & cpu_mask))
+			continue;
+
+		if (p->xtal_speed != sys_ck.rate)
+			continue;
+
+		if (p->mpu_speed <= mpu_speed) {
+			found_speed = p->mpu_speed;
+			break;
+		}
+	}
+
+	return found_speed;
+}
+
 static int omap2_enable_osc_ck(struct clk *clk)
 {
 	prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, 0,
@@ -176,9 +202,17 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 
 }
 
-static void omap2_dpllcore_recalc(struct clk *clk)
+static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate,
+				  u8 rate_storage)
 {
-	clk->rate = omap2xxx_clk_get_core_rate(clk);
+	unsigned long rate;
+
+	rate = omap2xxx_clk_get_core_rate(clk, parent_rate);
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
@@ -191,7 +225,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 	int ret = -EINVAL;
 
 	local_irq_save(flags);
-	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
+	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;
 
@@ -262,9 +296,18 @@ dpll_exit:
  *
  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
  */
-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)
 {
-	clk->rate = curr_prcm_set->mpu_speed;
+	struct prcm_config *prcm;
+	unsigned long mpurate;
+
+	mpurate = omap2xxx_clk_find_oppset_by_mpurate(parent_rate, &prcm);
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = mpurate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = mpurate;
 }
 
 /*
@@ -304,25 +347,12 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 {
 	u32 cur_rate, done_rate, bypass = 0, tmp;
 	struct prcm_config *prcm;
-	unsigned long found_speed = 0;
-	unsigned long flags;
+	unsigned long flags, found_speed;
 
 	if (clk != &virt_prcm_set)
 		return -EINVAL;
 
-	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-		if (!(prcm->flags & cpu_mask))
-			continue;
-
-		if (prcm->xtal_speed != sys_ck.rate)
-			continue;
-
-		if (prcm->mpu_speed <= rate) {
-			found_speed = prcm->mpu_speed;
-			break;
-		}
-	}
-
+	found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm);
 	if (!found_speed) {
 		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
 		       rate / 1000000);
@@ -330,7 +360,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 	}
 
 	curr_prcm_set = prcm;
-	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
+	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
 
 	if (prcm->dpll_speed == cur_rate / 2) {
 		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
@@ -463,14 +493,31 @@ static u32 omap2_get_sysclkdiv(void)
 	return div;
 }
 
-static void omap2_osc_clk_recalc(struct clk *clk)
+static void omap2_osc_clk_recalc(struct clk *clk, unsigned long parent_rate,
+				 u8 rate_storage)
 {
-	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
+	unsigned long rate;
+
+	/* XXX osc_ck on 2xxx currently is parentless */
+	rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
-static void omap2_sys_clk_recalc(struct clk *clk)
+static void omap2_sys_clk_recalc(struct clk *clk, unsigned long parent_rate,
+				 u8 rate_storage)
 {
-	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
+	unsigned long rate;
+
+	rate = parent_rate / omap2_get_sysclkdiv();
+
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = rate;
 }
 
 /*
@@ -523,8 +570,8 @@ int __init omap2_clk_init(void)
 
 	clk_init(&omap2_clk_functions);
 
-	omap2_osc_clk_recalc(&osc_ck);
-	omap2_sys_clk_recalc(&sys_ck);
+	omap2_osc_clk_recalc(&osc_ck, 0, CURRENT_RATE);
+	omap2_sys_clk_recalc(&sys_ck, sys_ck.parent->rate, CURRENT_RATE);
 
 	for (clkp = onchip_24xx_clks;
 	     clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
@@ -544,7 +591,7 @@ int __init omap2_clk_init(void)
 	}
 
 	/* Check the MPU rate set by bootloader */
-	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
+	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
 		if (!(prcm->flags & cpu_mask))
 			continue;
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 30f3c57..cd9feda 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -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);
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 22cbcce..917664d 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -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 */
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 66cbe0c..283c386 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -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,
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 4cf1145..7a7547d 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -83,8 +83,17 @@ int clk_enable(struct clk *clk)
 		return -EINVAL;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_enable)
+	if (arch_clock->clk_enable) {
 		ret = arch_clock->clk_enable(clk);
+		if (ret == 0 && clk->flags & RECALC_ON_ENABLE) {
+			if (clk->recalc)
+				(*clk->recalc)(clk, clk->parent->rate,
+					       CURRENT_RATE);
+			if (clk->flags & RATE_PROPAGATES)
+				propagate_rate(clk, CURRENT_RATE);
+		}
+	}
+
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -106,8 +115,16 @@ void clk_disable(struct clk *clk)
 		goto out;
 	}
 
-	if (arch_clock->clk_disable)
+	if (arch_clock->clk_disable) {
 		arch_clock->clk_disable(clk);
+		if (clk->flags & RECALC_ON_ENABLE) {
+			if (clk->recalc)
+				(*clk->recalc)(clk, clk->parent->rate,
+					       CURRENT_RATE);
+			if (clk->flags & RATE_PROPAGATES)
+				propagate_rate(clk, CURRENT_RATE);
+		}
+	}
 
 out:
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -188,9 +205,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 		ret = arch_clock->clk_set_rate(clk, rate);
 		if (ret == 0) {
 			if (clk->recalc)
-				(*clk->recalc)(clk);
+				(*clk->recalc)(clk, clk->parent->rate,
+					       CURRENT_RATE);
 			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk);
+				propagate_rate(clk, CURRENT_RATE);
 		}
 	}
 
@@ -214,9 +232,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 		ret = arch_clock->clk_set_parent(clk, parent);
 		if (ret == 0) {
 			if (clk->recalc)
-				(*clk->recalc)(clk);
+				(*clk->recalc)(clk, clk->parent->rate,
+					       CURRENT_RATE);
 			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk);
+				propagate_rate(clk, CURRENT_RATE);
 		}
 	}
 
@@ -268,18 +287,20 @@ static int __init omap_clk_setup(char *str)
 __setup("mpurate=", omap_clk_setup);
 
 /* Used for clocks that always have same value as the parent clock */
-void followparent_recalc(struct clk *clk)
+void followparent_recalc(struct clk *clk, unsigned long new_parent_rate,
+			 u8 rate_storage)
 {
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	clk->rate = clk->parent->rate;
+	if (rate_storage == CURRENT_RATE)
+		clk->rate = new_parent_rate;
+	else if (rate_storage == TEMP_RATE)
+		clk->temp_rate = new_parent_rate;
 }
 
 /* Propagate rate to children */
-void propagate_rate(struct clk * tclk)
+void propagate_rate(struct clk *tclk, u8 rate_storage)
 {
 	struct clk *clkp;
+	unsigned long parent_rate = 0;
 
 	if (tclk == NULL || IS_ERR(tclk))
 		return;
@@ -287,10 +308,16 @@ void propagate_rate(struct clk * tclk)
 	list_for_each_entry(clkp, &clocks, node) {
 		if (likely(clkp->parent != tclk))
 			continue;
+
+		if (rate_storage == CURRENT_RATE)
+			parent_rate = tclk->rate;
+		else if (rate_storage == TEMP_RATE)
+			parent_rate = tclk->temp_rate;
+
 		if (clkp->recalc)
-			clkp->recalc(clkp);
+			clkp->recalc(clkp, parent_rate, rate_storage);
 		if (clkp->flags & RATE_PROPAGATES)
-			propagate_rate(clkp);
+			propagate_rate(clkp, rate_storage);
 	}
 }
 
@@ -308,9 +335,9 @@ void recalculate_root_clocks(void)
 	list_for_each_entry(clkp, &clocks, node) {
 		if (unlikely(!clkp->parent)) {
 			if (clkp->recalc)
-				clkp->recalc(clkp);
+				clkp->recalc(clkp, 0, CURRENT_RATE);
 			if (clkp->flags & RATE_PROPAGATES)
-				propagate_rate(clkp);
+				propagate_rate(clkp, CURRENT_RATE);
 		}
 	}
 }
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index e793616..9b1d1f8 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -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)



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (9 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes Paul Walmsley
@ 2009-01-28 19:27 ` Paul Walmsley
  2009-01-29 15:14   ` Russell King - ARM Linux
  2009-01-29 19:52   ` Russell King - ARM Linux
  2009-01-28 19:28 ` [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta Paul Walmsley
                   ` (2 subsequent siblings)
  13 siblings, 2 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

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().

linux-omap source commit is c4cd1332c2a78112624f4a418116e95fa6e9e57c.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/clock.c             |    4 +
 arch/arm/plat-omap/clock.c              |  221 ++++++++++++++++++++++++-------
 arch/arm/plat-omap/include/mach/clock.h |   22 +++
 3 files changed, 199 insertions(+), 48 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 0c00706..6ca67cb 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -223,7 +223,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;
 			}
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 7a7547d..8417d11 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -23,6 +23,8 @@
 #include <linux/cpufreq.h>
 #include <linux/debugfs.h>
 #include <linux/io.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
 
 #include <mach/clock.h>
 
@@ -32,6 +34,142 @@ static DEFINE_SPINLOCK(clockfw_lock);
 
 static struct clk_functions *arch_clock;
 
+/**
+ * omap_clk_for_each_child - call callback on each child clock of clk
+ * @clk: struct clk * to use as the "parent"
+ * @parent_rate: rate of the parent of @clk to pass along
+ * @rate_storage: flag indicating whether current or temporary rates are used
+ * @cb: pointer to a callback function
+ *
+ * For each child clock of @clk, call the callback function @cb, passing
+ * along the contents of @parent_rate and @rate_storage.  If the callback
+ * function returns non-zero, terminate the function and pass along the
+ * return value.
+ */
+static int omap_clk_for_each_child(struct clk *clk, unsigned long parent_rate,
+				   u8 rate_storage,
+				   int (*cb)(struct clk *clk,
+					     unsigned long parent_rate,
+					     u8 rate_storage))
+{
+	struct clk_child *child;
+	int ret;
+
+	list_for_each_entry(child, &clk->children, node) {
+		ret = (*cb)(child->clk, parent_rate, rate_storage);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * omap_clk_has_children - does clk @clk have any child clocks?
+ * @clk: struct clk * to test for child clocks
+ *
+ * If clock @clk has any child clocks, return 1; otherwise, return 0.
+ */
+static int omap_clk_has_children(struct clk *clk)
+{
+	return (list_empty(&clk->children)) ? 0 : 1;
+}
+
+/**
+ * _do_propagate_rate - callback function for rate propagation
+ * @clk: struct clk * to recalc and propagate from
+ * @parent_rate: rate of the parent of @clk, to use in recalculation
+ * @rate_storage: flag indicating whether current or temporary rates are used
+ *
+ * If @clk has a recalc function, call it.  If @clk has any children,
+ * propagate @clk's rate.  Returns 0.
+ */
+static int _do_propagate_rate(struct clk *clk, unsigned long parent_rate,
+			      u8 rate_storage)
+{
+	if (clk->recalc)
+		clk->recalc(clk, parent_rate, rate_storage);
+	if (omap_clk_has_children(clk))
+		propagate_rate(clk, rate_storage);
+	return 0;
+}
+
+/**
+ * omap_clk_add_child - add a child clock @clk2 to @clk
+ * @clk: parent struct clk *
+ * @clk2: new child struct clk *
+ *
+ * Add a child clock @clk2 to the list of children of parent clock
+ * @clk.  Will potentially allocate memory from bootmem or, if
+ * available, from slab.  Must only be called with the clock framework
+ * spinlock held.  No return value.
+ */
+void omap_clk_add_child(struct clk *clk, struct clk *clk2)
+{
+	struct clk_child *child;
+	int reuse = 0;
+
+	if (!clk->children.next)
+		INIT_LIST_HEAD(&clk->children);
+
+	list_for_each_entry(child, &clk->children, node) {
+		if (child->flags & CLK_CHILD_DELETED) {
+			reuse = 1;
+			child->flags &= ~CLK_CHILD_DELETED;
+			break;
+		}
+	}
+
+	if (!reuse) {
+		if (slab_is_available())
+			child = kmalloc(sizeof(struct clk_child), GFP_ATOMIC);
+		else
+			child = alloc_bootmem(sizeof(struct clk_child));
+
+		if (!child) {
+			WARN_ON(1);
+			return;
+		}
+
+		memset(child, 0, sizeof(struct clk_child));
+
+		if (slab_is_available())
+			child->flags |= CLK_CHILD_SLAB_ALLOC;
+	}
+
+	child->clk = clk2;
+
+	list_add_tail(&child->node, &clk->children);
+}
+
+/**
+ * omap_clk_del_child - add a child clock @clk2 to @clk
+ * @clk: parent struct clk *
+ * @clk2: former child struct clk *
+ *
+ * Remove a child clock @clk2 from the list of children of parent
+ * clock @clk.  Must only be called with the clock framework spinlock
+ * held.  No return value.
+ */
+void omap_clk_del_child(struct clk *clk, struct clk *clk2)
+{
+	struct clk_child *child, *tmp;
+
+	/* Loop over all existing clk_childs, when found, deallocate */
+	list_for_each_entry_safe(child, tmp, &clk->children, node) {
+		if (child->clk == clk2) {
+			list_del(&child->node);
+			if (child->flags & CLK_CHILD_SLAB_ALLOC) {
+				kfree(child);
+			} else {
+				child->clk = NULL;
+				child->flags |= CLK_CHILD_DELETED;
+			}
+			break;
+		}
+	}
+}
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -85,13 +223,9 @@ int clk_enable(struct clk *clk)
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_enable) {
 		ret = arch_clock->clk_enable(clk);
-		if (ret == 0 && clk->flags & RECALC_ON_ENABLE) {
-			if (clk->recalc)
-				(*clk->recalc)(clk, clk->parent->rate,
-					       CURRENT_RATE);
-			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk, CURRENT_RATE);
-		}
+		if (ret == 0 && clk->flags & RECALC_ON_ENABLE)
+			_do_propagate_rate(clk, clk->parent->rate,
+					   CURRENT_RATE);
 	}
 
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -117,13 +251,9 @@ void clk_disable(struct clk *clk)
 
 	if (arch_clock->clk_disable) {
 		arch_clock->clk_disable(clk);
-		if (clk->flags & RECALC_ON_ENABLE) {
-			if (clk->recalc)
-				(*clk->recalc)(clk, clk->parent->rate,
-					       CURRENT_RATE);
-			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk, CURRENT_RATE);
-		}
+		if (clk->flags & RECALC_ON_ENABLE)
+			_do_propagate_rate(clk, clk->parent->rate,
+					   CURRENT_RATE);
 	}
 
 out:
@@ -203,13 +333,9 @@ 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) {
-			if (clk->recalc)
-				(*clk->recalc)(clk, clk->parent->rate,
-					       CURRENT_RATE);
-			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk, CURRENT_RATE);
-		}
+		if (ret == 0)
+			_do_propagate_rate(clk, clk->parent->rate,
+					   CURRENT_RATE);
 	}
 
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -221,6 +347,7 @@ EXPORT_SYMBOL(clk_set_rate);
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	unsigned long flags;
+	struct clk *prev_parent;
 	int ret = -EINVAL;
 
 	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
@@ -229,13 +356,13 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	spin_lock_irqsave(&clockfw_lock, flags);
 
 	if (arch_clock->clk_set_parent) {
+		prev_parent = clk->parent;
 		ret = arch_clock->clk_set_parent(clk, parent);
 		if (ret == 0) {
-			if (clk->recalc)
-				(*clk->recalc)(clk, clk->parent->rate,
-					       CURRENT_RATE);
-			if (clk->flags & RATE_PROPAGATES)
-				propagate_rate(clk, CURRENT_RATE);
+			omap_clk_del_child(prev_parent, clk);
+			omap_clk_add_child(parent, clk);
+			_do_propagate_rate(clk, clk->parent->rate,
+					   CURRENT_RATE);
 		}
 	}
 
@@ -299,26 +426,18 @@ void followparent_recalc(struct clk *clk, unsigned long new_parent_rate,
 /* Propagate rate to children */
 void propagate_rate(struct clk *tclk, u8 rate_storage)
 {
-	struct clk *clkp;
 	unsigned long parent_rate = 0;
 
 	if (tclk == NULL || IS_ERR(tclk))
 		return;
 
-	list_for_each_entry(clkp, &clocks, node) {
-		if (likely(clkp->parent != tclk))
-			continue;
-
-		if (rate_storage == CURRENT_RATE)
-			parent_rate = tclk->rate;
-		else if (rate_storage == TEMP_RATE)
-			parent_rate = tclk->temp_rate;
+	if (rate_storage == CURRENT_RATE)
+		parent_rate = tclk->rate;
+	else if (rate_storage == TEMP_RATE)
+		parent_rate = tclk->temp_rate;
 
-		if (clkp->recalc)
-			clkp->recalc(clkp, parent_rate, rate_storage);
-		if (clkp->flags & RATE_PROPAGATES)
-			propagate_rate(clkp, rate_storage);
-	}
+	omap_clk_for_each_child(tclk, parent_rate, rate_storage,
+				_do_propagate_rate);
 }
 
 /**
@@ -332,14 +451,9 @@ void recalculate_root_clocks(void)
 {
 	struct clk *clkp;
 
-	list_for_each_entry(clkp, &clocks, node) {
-		if (unlikely(!clkp->parent)) {
-			if (clkp->recalc)
-				clkp->recalc(clkp, 0, CURRENT_RATE);
-			if (clkp->flags & RATE_PROPAGATES)
-				propagate_rate(clkp, CURRENT_RATE);
-		}
-	}
+	list_for_each_entry(clkp, &clocks, node)
+		if (unlikely(!clkp->parent))
+			_do_propagate_rate(clkp, 0, CURRENT_RATE);
 }
 
 int clk_register(struct clk *clk)
@@ -349,6 +463,10 @@ int clk_register(struct clk *clk)
 
 	mutex_lock(&clocks_mutex);
 	list_add(&clk->node, &clocks);
+	if (!clk->children.next)
+		INIT_LIST_HEAD(&clk->children);
+	if (clk->parent)
+		omap_clk_add_child(clk->parent, clk);
 	if (clk->init)
 		clk->init(clk);
 	mutex_unlock(&clocks_mutex);
@@ -359,11 +477,18 @@ EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
+	struct clk_child *child, *tmp;
+
 	if (clk == NULL || IS_ERR(clk))
 		return;
 
 	mutex_lock(&clocks_mutex);
 	list_del(&clk->node);
+	if (clk->parent)
+		omap_clk_del_child(clk->parent, clk);
+	list_for_each_entry_safe(child, tmp, &clk->children, node)
+		if (child->flags & CLK_CHILD_SLAB_ALLOC)
+			kfree(child);
 	mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 9b1d1f8..358bf9e 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -60,6 +60,21 @@ struct dpll_data {
 
 #endif
 
+/**
+ * struct clk_child - used to track the children of a clock
+ * @clk: child struct clk *
+ * @node: list_head
+ * @flags: is this entry allocated in bootmem or slab?  is it deleted?
+ *
+ * One struct clk_child is allocated for each child clock @clk of a
+ * parent clock.  @flags values are listed below and start with CLK_CHILD_*.
+ */
+struct clk_child {
+	struct clk		*clk;
+	struct list_head	node;
+	u8			flags;
+};
+
 struct clk {
 	struct list_head	node;
 	struct module		*owner;
@@ -68,6 +83,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 +148,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 +192,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)



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (10 preceding siblings ...)
  2009-01-28 19:27 ` [PATCH E 11/14] OMAP clock: track child clocks Paul Walmsley
@ 2009-01-28 19:28 ` Paul Walmsley
  2009-02-23 15:50   ` Russell King - ARM Linux
  2009-01-28 19:28 ` [PATCH E 13/14] OMAP2/3 clock: remove clk->owner Paul Walmsley
  2009-01-28 19:28 ` [PATCH E 14/14] OMAP clock: rearrange clock.h structure order Paul Walmsley
  13 siblings, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel; +Cc: linux-omap, Paul Walmsley, Tony Lindgren

This patch removes four unnecessary clock flags:

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

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

3. Nothing tests the clock flags for VIRTUAL_CLOCK, so it serves no
purpose.  Remove it.

4. 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.

linux-omap source commits are ed950086c69beaabd7179a13b9d2f6c6d0cbddc8,
563aab5521064eae3ece7f3f1f19a32cb5cece4a,
ab0f0e3e3625d5b9abaf37133478c69b4a193521, and
f438e7e9dcd837fd64109256fce82725f7887428.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap1/clock.c             |    3 
 arch/arm/mach-omap1/clock.h             |   44 +++---
 arch/arm/mach-omap2/clock.c             |   17 --
 arch/arm/mach-omap2/clock24xx.h         |   72 ++++------
 arch/arm/mach-omap2/clock34xx.h         |  217 +++++++++++--------------------
 arch/arm/plat-omap/include/mach/clock.h |    8 -
 6 files changed, 130 insertions(+), 231 deletions(-)

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index f3cf6f8..af48050 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -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)
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index df94ad6..5ba55a0 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -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,
@@ -555,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,
@@ -603,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,
@@ -618,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,
@@ -630,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,
@@ -642,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,
@@ -654,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,
@@ -665,7 +663,7 @@ 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,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
 	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
 	.enable_bit	= 6,
 	.enable		= &omap1_clk_enable_generic,
@@ -689,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,
 };
@@ -713,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,
@@ -727,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,
@@ -738,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,
@@ -753,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,
@@ -764,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,
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 6ca67cb..07b6232 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -561,8 +561,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.
  */
@@ -623,8 +621,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.
  */
@@ -642,10 +638,6 @@ long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
 	if (clk->round_rate)
 		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;
 }
 
@@ -780,12 +772,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)
 		ret = clk->set_rate(clk, rate);
 
@@ -830,9 +816,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;
 
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index cd9feda..2b7b473 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -628,15 +628,14 @@ static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.rate		= 32000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
 static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
 	.name		= "osc_ck",
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable		= &omap2_enable_osc_ck,
 	.disable	= &omap2_disable_osc_ck,
@@ -648,7 +647,7 @@ static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
 	.name		= "sys_ck",		/* ~ ref_clk also */
 	.parent		= &osc_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_sys_clk_recalc,
 };
@@ -657,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 | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -692,7 +691,7 @@ static struct clk dpll_ck = {
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll_dd,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | ALWAYS_ENABLED,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_dpllcore_recalc,
 	.set_rate	= &omap2_reprogram_dpllcore,
@@ -704,7 +703,7 @@ static struct clk apll96_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 96000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
@@ -718,7 +717,7 @@ static struct clk apll54_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
@@ -753,7 +752,7 @@ static struct clk func_54m_ck = {
 	.parent		= &apll54_ck,	/* can also be alt_clk */
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -766,7 +765,7 @@ static struct clk core_ck = {
 	.name		= "core_ck",
 	.parent		= &dpll_ck,		/* can also be 32k */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -794,7 +793,7 @@ static struct clk func_96m_ck = {
 	.parent		= &apll96_ck,
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -828,7 +827,7 @@ static struct clk func_48m_ck = {
 	.parent		= &apll96_ck,	 /* 96M or Alt */
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -844,7 +843,7 @@ static struct clk func_12m_ck = {
 	.parent		= &func_48m_ck,
 	.fixed_div	= 4,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -898,8 +897,7 @@ static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
 	.prcm_mod	= OMAP24XX_GR_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL_OFFSET,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
@@ -946,7 +944,7 @@ static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
 	.prcm_mod	= OMAP24XX_GR_MOD,
-	.flags		= CLOCK_IN_OMAP242X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm		= { .name = "cm_clkdm" },
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL_OFFSET,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
@@ -1020,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 | RATE_PROPAGATES,
+				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
 };
 
 /*
@@ -1063,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 | RATE_PROPAGATES,
+	.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,
@@ -1072,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 */
@@ -1095,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 */
@@ -1110,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 */
@@ -1121,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,
@@ -1136,8 +1126,7 @@ static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
-				RATE_PROPAGATES | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
 	.clkdm		= { .name = "iva1_clkdm" },
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
@@ -1202,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 | RATE_PROPAGATES,
+				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 */
@@ -1231,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,
@@ -1241,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
 };
 
 /*
@@ -1268,7 +1252,7 @@ static struct clk l4_ck = {		/* used both as an ick and fck */
 	.parent		= &core_l3_ck,
 	.prcm_mod	= CORE_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
+				ALWAYS_ENABLED | DELAYED_APP,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
@@ -1348,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[] = {
@@ -1423,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,
@@ -1431,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 = {
@@ -2848,7 +2830,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 */
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 283c386..179ea17 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -66,16 +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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -83,48 +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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -178,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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -205,14 +196,14 @@ static struct clk sys_ck = {
 	.clksel_reg	= OMAP3_PRM_CLKSRC_CTRL_OFFSET,
 	.clksel_mask	= OMAP_SYSCLKDIV_MASK,
 	.clksel		= sys_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk sys_altclk = {
 	.name		= "sys_altclk",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "cm_clkdm" },
 };
 
@@ -223,7 +214,7 @@ static struct clk sys_altclk = {
  */
 static struct clk mcbsp_clks = {
 	.name		= "mcbsp_clks",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -294,8 +285,7 @@ static struct clk dpll1_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= MPU_MOD,
 	.dpll_data	= &dpll1_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 	.clkdm		= { .name = "dpll1_clkdm" },
@@ -309,8 +299,7 @@ static struct clk dpll1_ck = {
 static struct clk dpll1_x2_ck = {
 	.name		= "dpll1_x2_ck",
 	.parent		= &dpll1_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll1_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -333,8 +322,7 @@ static struct clk dpll1_x2m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL2_PLL,
 	.clksel_mask	= OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll1_x2m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll1_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -371,8 +359,7 @@ static struct clk dpll2_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= OMAP3430_IVA2_MOD,
 	.dpll_data	= &dpll2_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -398,8 +385,7 @@ static struct clk dpll2_m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL2_PLL,
 	.clksel_mask	= OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll2_m2x2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll2_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -435,8 +421,7 @@ static struct clk dpll3_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll3_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_dpll_recalc,
@@ -449,8 +434,7 @@ static struct clk dpll3_ck = {
 static struct clk dpll3_x2_ck = {
 	.name		= "dpll3_x2_ck",
 	.parent		= &dpll3_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -504,8 +488,7 @@ static struct clk dpll3_m2_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div31_dpll3m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap3_core_dpll_m2_set_rate,
@@ -515,8 +498,7 @@ static struct clk dpll3_m2_ck = {
 static struct clk core_ck = {
 	.name		= "core_ck",
 	.parent		= &dpll3_m2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -524,8 +506,7 @@ static struct clk core_ck = {
 static struct clk dpll3_m2x2_ck = {
 	.name		= "dpll3_m2x2_ck",
 	.parent		= &dpll3_x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -545,8 +526,7 @@ static struct clk dpll3_m3_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_DIV_DPLL3_MASK,
 	.clksel		= div16_dpll3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -558,7 +538,7 @@ static struct clk dpll3_m3x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -566,8 +546,7 @@ static struct clk dpll3_m3x2_ck = {
 static struct clk emu_core_alwon_ck = {
 	.name		= "emu_core_alwon_ck",
 	.parent		= &dpll3_m3x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -602,8 +581,7 @@ static struct clk dpll4_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll4_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -620,8 +598,7 @@ static struct clk dpll4_ck = {
 static struct clk dpll4_x2_ck = {
 	.name		= "dpll4_x2_ck",
 	.parent		= &dpll4_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -640,8 +617,7 @@ static struct clk dpll4_m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL3,
 	.clksel_mask	= OMAP3430_DIV_96M_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -653,7 +629,7 @@ static struct clk dpll4_m2x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -667,8 +643,7 @@ static struct clk dpll4_m2x2_ck = {
 static struct clk omap_96m_alwon_fck = {
 	.name		= "omap_96m_alwon_fck",
 	.parent		= &dpll4_m2x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -676,8 +651,7 @@ static struct clk omap_96m_alwon_fck = {
 static struct clk cm_96m_fck = {
 	.name		= "cm_96m_fck",
 	.parent		= &omap_96m_alwon_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -706,8 +680,7 @@ static struct clk omap_96m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_96M_MASK,
 	.clksel		= omap_96m_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -721,8 +694,7 @@ static struct clk dpll4_m3_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_TV_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -735,7 +707,7 @@ static struct clk dpll4_m3x2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -763,8 +735,7 @@ static struct clk omap_54m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_54M_MASK,
 	.clksel		= omap_54m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -792,8 +763,7 @@ static struct clk omap_48m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_48M_MASK,
 	.clksel		= omap_48m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -802,8 +772,7 @@ static struct clk omap_12m_fck = {
 	.name		= "omap_12m_fck",
 	.parent		= &omap_48m_fck,
 	.fixed_div	= 4,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -817,8 +786,7 @@ static struct clk dpll4_m4_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_DSS1_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -832,7 +800,7 @@ static struct clk dpll4_m4x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_DSS1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -846,8 +814,7 @@ static struct clk dpll4_m5_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_CAM_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -859,7 +826,7 @@ static struct clk dpll4_m5x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -873,8 +840,7 @@ static struct clk dpll4_m6_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_DIV_DPLL4_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -887,7 +853,7 @@ static struct clk dpll4_m6x2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -895,8 +861,7 @@ static struct clk dpll4_m6x2_ck = {
 static struct clk emu_per_alwon_ck = {
 	.name		= "emu_per_alwon_ck",
 	.parent		= &dpll4_m6x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -932,8 +897,7 @@ static struct clk dpll5_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll5_dd,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP3430ES2 | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -955,8 +919,7 @@ static struct clk dpll5_m2_ck = {
 	.clksel_reg	= OMAP3430ES2_CM_CLKSEL5,
 	.clksel_mask	= OMAP3430ES2_DIV_120M_MASK,
 	.clksel		= div16_dpll5_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP3430ES2 | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll5_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1000,7 +963,7 @@ static struct clk clkout2_src_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL_OFFSET,
 	.clksel_mask	= OMAP3430_CLKOUT2SOURCE_MASK,
 	.clksel		= clkout2_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1036,8 +999,7 @@ static struct clk sys_clkout2 = {
 static struct clk corex2_fck = {
 	.name		= "corex2_fck",
 	.parent		= &dpll3_m2x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1064,8 +1026,7 @@ static struct clk dpll1_fck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL1_PLL,
 	.clksel_mask	= OMAP3430_MPU_CLK_SRC_MASK,
 	.clksel		= div4_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1073,8 +1034,7 @@ static struct clk dpll1_fck = {
 static struct clk mpu_ck = {
 	.name		= "mpu_ck",
 	.parent		= &dpll1_x2m2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1099,8 +1059,7 @@ static struct clk arm_fck = {
 	.clksel_reg	= OMAP3430_CM_IDLEST_PLL,
 	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
 	.clksel		= arm_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1114,8 +1073,7 @@ static struct clk arm_fck = {
 static struct clk emu_mpu_alwon_ck = {
 	.name		= "emu_mpu_alwon_ck",
 	.parent		= &mpu_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1128,8 +1086,7 @@ static struct clk dpll2_fck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL1_PLL,
 	.clksel_mask	= OMAP3430_IVA2_CLK_SRC_MASK,
 	.clksel		= div4_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1141,7 +1098,7 @@ static struct clk iva2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm		= { .name = "iva2_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1161,8 +1118,7 @@ static struct clk l3_ick = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_L3_MASK,
 	.clksel		= div2_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1180,8 +1136,7 @@ static struct clk l4_ick = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_L4_MASK,
 	.clksel		= div2_l3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 
@@ -1235,8 +1190,7 @@ static struct clk gfx_l3_fck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_l3_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "gfx_3430es1_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1407,8 +1361,7 @@ static struct clk usbtll_fck = {
 static struct clk core_96m_fck = {
 	.name		= "core_96m_fck",
 	.parent		= &omap_96m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1579,8 +1532,7 @@ static struct clk mcbsp1_fck = {
 static struct clk core_48m_fck = {
 	.name		= "core_48m_fck",
 	.parent		= &omap_48m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1679,8 +1631,7 @@ static struct clk fshostusb_fck = {
 static struct clk core_12m_fck = {
 	.name		= "core_12m_fck",
 	.parent		= &omap_12m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1723,7 +1674,7 @@ static struct clk ssi_ssr_fck_3430es1 = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1738,7 +1689,7 @@ static struct clk ssi_ssr_fck_3430es2 = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP3430ES2 | WAIT_READY,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1773,8 +1724,7 @@ static struct clk ssi_sst_fck_3430es2 = {
 static struct clk core_l3_ick = {
 	.name		= "core_l3_ick",
 	.parent		= &l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1828,8 +1778,7 @@ static struct clk gpmc_fck = {
 static struct clk security_l3_ick = {
 	.name		= "security_l3_ick",
 	.parent		= &l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1851,8 +1800,7 @@ static struct clk pka_ick = {
 static struct clk core_l4_ick = {
 	.name		= "core_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2186,8 +2134,7 @@ static struct clk omapctrl_ick = {
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2247,8 +2194,7 @@ static struct clk usb_l4_ick = {
 static struct clk security_l4_ick2 = {
 	.name		= "security_l4_ick2",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2518,7 +2464,7 @@ static struct clk gpt1_fck = {
 static struct clk wkup_32k_fck = {
 	.name		= "wkup_32k_fck",
 	.parent		= &omap_32k_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2550,7 +2496,7 @@ static struct clk wdt2_fck = {
 static struct clk wkup_l4_ick = {
 	.name		= "wkup_l4_ick",
 	.parent		= &sys_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2646,8 +2592,7 @@ static struct clk gpt1_ick = {
 static struct clk per_96m_fck = {
 	.name		= "per_96m_fck",
 	.parent		= &omap_96m_alwon_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2655,8 +2600,7 @@ static struct clk per_96m_fck = {
 static struct clk per_48m_fck = {
 	.name		= "per_48m_fck",
 	.parent		= &omap_48m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2797,7 +2741,7 @@ static struct clk per_32k_alwon_fck = {
 	.name		= "per_32k_alwon_fck",
 	.parent		= &omap_32k_fck,
 	.clkdm		= { .name = "per_clkdm" },
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2876,8 +2820,7 @@ static struct clk wdt3_fck = {
 static struct clk per_l4_ick = {
 	.name		= "per_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -3229,7 +3172,7 @@ static struct clk emu_src_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3254,7 +3197,7 @@ static struct clk pclk_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_PCLK_MASK,
 	.clksel		= pclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3278,7 +3221,7 @@ static struct clk pclkx2_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_PCLKX2_MASK,
 	.clksel		= pclkx2_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3295,7 +3238,7 @@ static struct clk atclk_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_ATCLK_MASK,
 	.clksel		= atclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3307,7 +3250,7 @@ static struct clk traceclk_src_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_TRACE_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3346,7 +3289,7 @@ static struct clk sr1_fck = {
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
 	.idlest_bit	= OMAP3430_ST_SR1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP343X | WAIT_READY,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -3359,7 +3302,7 @@ static struct clk sr2_fck = {
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
 	.idlest_bit	= OMAP3430_ST_SR2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP343X | WAIT_READY,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 358bf9e..a039832 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -153,16 +153,14 @@ 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 */
+/* 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 */
-#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 */



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 13/14] OMAP2/3 clock: remove clk->owner
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (11 preceding siblings ...)
  2009-01-28 19:28 ` [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta Paul Walmsley
@ 2009-01-28 19:28 ` Paul Walmsley
  2009-01-28 19:28 ` [PATCH E 14/14] OMAP clock: rearrange clock.h structure order Paul Walmsley
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: linux-omap, Russell King, Paul Walmsley, Tony Lindgren

From: Russell King <rmk@dyn-67.arm.linux.org.uk>

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

linux-omap source commit is 59ae1e06b177e462d75586d83380f18a7024e77b.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/clock.c              |    7 ++-----
 arch/arm/plat-omap/include/mach/clock.h |    1 -
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 8417d11..2a4819f 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -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);
 
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index a039832..58450a1 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -77,7 +77,6 @@ struct clk_child {
 
 struct clk {
 	struct list_head	node;
-	struct module		*owner;
 	const char		*name;
 	int			id;
 	struct clk		*parent;



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH E 14/14] OMAP clock: rearrange clock.h structure order
  2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
                   ` (12 preceding siblings ...)
  2009-01-28 19:28 ` [PATCH E 13/14] OMAP2/3 clock: remove clk->owner Paul Walmsley
@ 2009-01-28 19:28 ` Paul Walmsley
  13 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-28 19:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: linux-omap, Russell King, Paul Walmsley, Tony Lindgren

From: Russell King <rmk@dyn-67.arm.linux.org.uk>

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

[paul@pwsan.com: updated against current linux-omap clock tree, now saves
1512 bytes on OMAP3 builds]

linux-omap source commit is 64a423d87fae87608642c28393bb440b45e5e25e.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/include/mach/clock.h |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 58450a1..9d38a25 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -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
 };
 
@@ -85,18 +85,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;
@@ -104,6 +103,7 @@ struct clk {
 		const char		*name;
 		struct clockdomain	*ptr;
 	} clkdm;
+	u16			clksel_reg;
 	s16			prcm_mod;
 #else
 	__u8			rate_offset;



^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-28 19:27 ` [PATCH E 11/14] OMAP clock: track child clocks Paul Walmsley
@ 2009-01-29 15:14   ` Russell King - ARM Linux
  2009-01-29 22:06     ` Russell King - ARM Linux
  2009-01-29 19:52   ` Russell King - ARM Linux
  1 sibling, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-29 15:14 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:27:59PM -0700, Paul Walmsley wrote:
> The price paid is additional runtime memory consumption - 8 bytes per
> clock and 16 bytes per child clock - roughly 4.5KiB on OMAP3.

For OMAP3, that's 222 struct clks of which 182 are children, and indeed
222 * 8 + 182 * 16 gives about 4.5K.  On OMAP2, it's 140 and 136,
giving 140 * 8 + 136 * 16 = 3.3K.

Moving struct clk_child into struct clk means that its clk and flags
members can be deleted, making it 8 bytes in size - effectively just
the list_head.  We need a list_head for the 'children' as you have it.
So, that works out as 16 bytes per clock.  That gives 3.5K on OMAP3
and 2.2K on OMAP2.

So, by taking that alternative approach, not only do you end up using
less memory, but you also don't have to have the overhead of your
custom memory bookkeeping.

The other change I'd suggest is that you have one function which deals
with setting the parent of a clock:

void clk_reparent(struct clk *child, struct clk *parent)
{
	list_del_init(&child->sibling);
	if (parent)
		list_add(&child->sibling, &parent->children);
	child->parent = parent;

	/* now do the debugfs renaming to reattach the child
	   to the proper parent */
}

which is a lot simpler than your omap_clk_add_child() and omap_clk_del_child().

These should be in the _core_ OMAP clock code, not just in the OMAP2
clock code.  OMAP1 has child clocks as well as OMAP2.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-28 19:27 ` [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c Paul Walmsley
@ 2009-01-29 17:41   ` Russell King - ARM Linux
  2009-01-30  8:42     ` Paul Walmsley
  0 siblings, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-29 17:41 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:27:51PM -0700, Paul Walmsley wrote:
> 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.

I must say that this commit looks very much like a combination of
my commits from November:

[ARM] omap: move clock propagation into core omap clock code
[ARM] omap: remove unnecessary calls to propagate_rate()
[ARM] omap: move propagate_rate() calls into generic omap clock code

which do basically the same thing a little more efficiently, and an
additional patch from you to call ->recalc after set_rate or
reparenting a clock.

So I think I can drop everything from this apart from the additional
recalc calls, and the removal of those omap2_dpllcore_recalc() calls.

Please confirm my suspicions.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-28 19:27 ` [PATCH E 11/14] OMAP clock: track child clocks Paul Walmsley
  2009-01-29 15:14   ` Russell King - ARM Linux
@ 2009-01-29 19:52   ` Russell King - ARM Linux
  2009-02-02  7:57     ` Paul Walmsley
  1 sibling, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-29 19:52 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:27:59PM -0700, Paul Walmsley wrote:
> +static int omap_clk_for_each_child(struct clk *clk, unsigned long parent_rate,
> +		   u8 rate_storage, int (*cb)(struct clk *, unsigned long, u8))
> +{
> +	struct clk_child *child;
> +	int ret;
> +
> +	list_for_each_entry(child, &clk->children, node) {
> +		ret = (*cb)(child->clk, parent_rate, rate_storage);
> +		if (ret)
> +			break;
> +	}
> +
> +	return ret;
> +}

> +static int _do_propagate_rate(struct clk *clk, unsigned long parent_rate,
> +			      u8 rate_storage)
> +{
> +	if (clk->recalc)
> +		clk->recalc(clk, parent_rate, rate_storage);
> +	if (omap_clk_has_children(clk))
> +		propagate_rate(clk, rate_storage);
> +	return 0;
> +}

>  /* Propagate rate to children */
>  void propagate_rate(struct clk *tclk, u8 rate_storage)
>  {
>  	unsigned long parent_rate = 0;
>  
>  	if (tclk == NULL || IS_ERR(tclk))
>  		return;
>  
> +	if (rate_storage == CURRENT_RATE)
> +		parent_rate = tclk->rate;
> +	else if (rate_storage == TEMP_RATE)
> +		parent_rate = tclk->temp_rate;
>  
> +	omap_clk_for_each_child(tclk, parent_rate, rate_storage,
> +				_do_propagate_rate);
>  }

This worries me.  Calling this puts onto the stack:

- a frame for propagate_rate()
- a frame for omap_clk_for_each_child
- a frame for _do_propagate_rate

for every level of children.  How close we get to overflowing the kernels
depends on how much each of those functions puts on the kernel stack.
However, since this is recursive, minimising the number of stack frames
is a good idea.

That's why I have in my patch:

 [ARM] omap: move propagate_rate() calls into generic omap clock code

I've arranged for there to be the minimum of function nesting here.
I suggest keeping this.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-29 15:14   ` Russell King - ARM Linux
@ 2009-01-29 22:06     ` Russell King - ARM Linux
  2009-01-30  8:35       ` Paul Walmsley
                         ` (2 more replies)
  0 siblings, 3 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-29 22:06 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Thu, Jan 29, 2009 at 03:14:01PM +0000, Russell King - ARM Linux wrote:
> On Wed, Jan 28, 2009 at 12:27:59PM -0700, Paul Walmsley wrote:
> > The price paid is additional runtime memory consumption - 8 bytes per
> > clock and 16 bytes per child clock - roughly 4.5KiB on OMAP3.
> 
> For OMAP3, that's 222 struct clks of which 182 are children, and indeed
> 222 * 8 + 182 * 16 gives about 4.5K.  On OMAP2, it's 140 and 136,
> giving 140 * 8 + 136 * 16 = 3.3K.
> 
> Moving struct clk_child into struct clk means that its clk and flags
> members can be deleted, making it 8 bytes in size - effectively just
> the list_head.  We need a list_head for the 'children' as you have it.
> So, that works out as 16 bytes per clock.  That gives 3.5K on OMAP3
> and 2.2K on OMAP2.
> 
> So, by taking that alternative approach, not only do you end up using
> less memory, but you also don't have to have the overhead of your
> custom memory bookkeeping.
> 
> The other change I'd suggest is that you have one function which deals
> with setting the parent of a clock:
> 
> void clk_reparent(struct clk *child, struct clk *parent)
> {
> 	list_del_init(&child->sibling);
> 	if (parent)
> 		list_add(&child->sibling, &parent->children);
> 	child->parent = parent;
> 
> 	/* now do the debugfs renaming to reattach the child
> 	   to the proper parent */
> }
> 
> which is a lot simpler than your omap_clk_add_child() and omap_clk_del_child().
> 
> These should be in the _core_ OMAP clock code, not just in the OMAP2
> clock code.  OMAP1 has child clocks as well as OMAP2.

And here is my version of this patch:

 arch/arm/mach-omap2/clock.c             |    4 +-
 arch/arm/plat-omap/clock.c              |   49 +++++++++++++++++++------------
 arch/arm/plat-omap/include/mach/clock.h |    3 ++
 3 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 56d9ea4..14bf566 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -175,7 +175,7 @@ void omap2_init_clksel_parent(struct clk *clk)
 						 clk->name, clks->parent->name,
 						 ((clk->parent) ?
 						  clk->parent->name : "NULL"));
-					clk->parent = clks->parent;
+					clk_reparent(clk, clks->parent);
 				};
 				found = 1;
 			}
@@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	if (clk->usecount > 0)
 		_omap2_clk_enable(clk);
 
-	clk->parent = new_parent;
+	clk_reparent(clk, new_parent);
 
 	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
 	clk->rate = new_parent->rate;
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3688400..58e42b1 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -127,8 +127,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (ret == 0) {
 		if (clk->recalc)
 			clk->recalc(clk);
-		if (clk->flags & RATE_PROPAGATES)
-			propagate_rate(clk);
+		propagate_rate(clk);
 	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
@@ -150,8 +149,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (ret == 0) {
 		if (clk->recalc)
 			clk->recalc(clk);
-		if (clk->flags & RATE_PROPAGATES)
-			propagate_rate(clk);
+		propagate_rate(clk);
 	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
@@ -192,27 +190,34 @@ void followparent_recalc(struct clk *clk)
 	clk->rate = clk->parent->rate;
 }
 
+void clk_reparent(struct clk *child, struct clk *parent)
+{
+	list_del_init(&child->sibling);
+	if (parent)
+		list_add(&child->sibling, &parent->children);
+	child->parent = parent;
+
+	/* now do the debugfs renaming to reattach the child
+	   to the proper parent */
+}
+
 /* Propagate rate to children */
 void propagate_rate(struct clk * tclk)
 {
 	struct clk *clkp;
 
-	if (tclk == NULL || IS_ERR(tclk))
-		return;
-
-	list_for_each_entry(clkp, &clocks, node) {
-		if (likely(clkp->parent != tclk))
-			continue;
+	list_for_each_entry(clkp, &tclk->children, sibling) {
 		if (clkp->recalc) {
 			unsigned long old_rate = clkp->rate;
 			clkp->recalc(clkp);
-			if (clkp->rate != old_rate &&
-			    (clkp->flags & RATE_PROPAGATES))
+			if (clkp->rate != old_rate)
 				propagate_rate(clkp);
 		}
 	}
 }
 
+static LIST_HEAD(root_clks);
+
 /**
  * recalculate_root_clocks - recalculate and propagate all root clocks
  *
@@ -224,13 +229,10 @@ void recalculate_root_clocks(void)
 {
 	struct clk *clkp;
 
-	list_for_each_entry(clkp, &clocks, node) {
-		if (!clkp->parent) {
-			if (clkp->recalc)
-				clkp->recalc(clkp);
-			if (clkp->flags & RATE_PROPAGATES)
-				propagate_rate(clkp);
-		}
+	list_for_each_entry(clkp, &root_clks, sibling) {
+		if (clkp->recalc)
+			clkp->recalc(clkp);
+		propagate_rate(clkp);
 	}
 }
 
@@ -246,6 +248,15 @@ int clk_register(struct clk *clk)
 		return 0;
 
 	mutex_lock(&clocks_mutex);
+	if (!clk->children.next)
+		INIT_LIST_HEAD(&clk->children);
+	if (clk->parent && !clk->parent->children.next)
+		INIT_LIST_HEAD(&clk->parent->children);
+	if (clk->parent)
+		list_add(&clk->sibling, &clk->parent->children);
+	else
+		list_add(&clk->sibling, &root_clks);
+
 	list_add(&clk->node, &clocks);
 	if (clk->init)
 		clk->init(clk);
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index ad0345f..3504c2b 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -70,6 +70,8 @@ struct clk {
 	const char		*name;
 	int			id;
 	struct clk		*parent;
+	struct list_head	children;
+	struct list_head	sibling;	/* node for children */
 	unsigned long		rate;
 	__u32			flags;
 	void __iomem		*enable_reg;
@@ -116,6 +118,7 @@ extern unsigned int mpurate;
 
 extern int clk_init(struct clk_functions *custom_clocks);
 extern int clk_register(struct clk *clk);
+extern void clk_reparent(struct clk *child, struct clk *parent);
 extern void clk_unregister(struct clk *clk);
 extern void propagate_rate(struct clk *clk);
 extern void recalculate_root_clocks(void);

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-29 22:06     ` Russell King - ARM Linux
@ 2009-01-30  8:35       ` Paul Walmsley
  2009-02-02  4:57       ` Paul Walmsley
  2009-02-09 14:11       ` Russell King - ARM Linux
  2 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-30  8:35 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Thu, 29 Jan 2009, Russell King - ARM Linux wrote:

> On Thu, Jan 29, 2009 at 03:14:01PM +0000, Russell King - ARM Linux wrote:
> > On Wed, Jan 28, 2009 at 12:27:59PM -0700, Paul Walmsley wrote:
> > > The price paid is additional runtime memory consumption - 8 bytes per
> > > clock and 16 bytes per child clock - roughly 4.5KiB on OMAP3.
> > 
> > For OMAP3, that's 222 struct clks of which 182 are children, and indeed
> > 222 * 8 + 182 * 16 gives about 4.5K.  On OMAP2, it's 140 and 136,
> > giving 140 * 8 + 136 * 16 = 3.3K.
> > 
> > Moving struct clk_child into struct clk means that its clk and flags
> > members can be deleted, making it 8 bytes in size - effectively just
> > the list_head.  We need a list_head for the 'children' as you have it.
> > So, that works out as 16 bytes per clock.  That gives 3.5K on OMAP3
> > and 2.2K on OMAP2.
> > 
> > So, by taking that alternative approach, not only do you end up using
> > less memory, but you also don't have to have the overhead of your
> > custom memory bookkeeping.
> > 
> > The other change I'd suggest is that you have one function which deals
> > with setting the parent of a clock:
> > 
> > void clk_reparent(struct clk *child, struct clk *parent)
> > {
> > 	list_del_init(&child->sibling);
> > 	if (parent)
> > 		list_add(&child->sibling, &parent->children);
> > 	child->parent = parent;
> > 
> > 	/* now do the debugfs renaming to reattach the child
> > 	   to the proper parent */
> > }
> > 
> > which is a lot simpler than your omap_clk_add_child() and omap_clk_del_child().
> > 
> > These should be in the _core_ OMAP clock code, not just in the OMAP2
> > clock code.  OMAP1 has child clocks as well as OMAP2.
> 
> And here is my version of this patch:

Thanks, I'll take a closer look at this later today.


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-29 17:41   ` Russell King - ARM Linux
@ 2009-01-30  8:42     ` Paul Walmsley
  2009-01-30  8:52       ` Russell King - ARM Linux
  2009-02-02  7:13       ` Paul Walmsley
  0 siblings, 2 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-01-30  8:42 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell, 

On Thu, 29 Jan 2009, Russell King - ARM Linux wrote:

> On Wed, Jan 28, 2009 at 12:27:51PM -0700, Paul Walmsley wrote:
> > 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.
> 
> I must say that this commit looks very much like a combination of
> my commits from November:
> 
> [ARM] omap: move clock propagation into core omap clock code
> [ARM] omap: remove unnecessary calls to propagate_rate()
> [ARM] omap: move propagate_rate() calls into generic omap clock code
> 
> which do basically the same thing a little more efficiently, and an
> additional patch from you to call ->recalc after set_rate or
> reparenting a clock.
> 
> So I think I can drop everything from this apart from the additional
> recalc calls, and the removal of those omap2_dpllcore_recalc() calls.
> 
> Please confirm my suspicions.

I haven't looked closely at your above three patches for this, but plan to 
do so later today.

Regarding provenance, the patches that I sent you were developed 
independently, for clock notifier support.  Ultimately, I have no personal 
attachment as to whose patches for this go in, if all technical aspects 
are equal.


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-30  8:42     ` Paul Walmsley
@ 2009-01-30  8:52       ` Russell King - ARM Linux
  2009-01-30 14:23         ` Woodruff, Richard
  2009-02-02  7:13       ` Paul Walmsley
  1 sibling, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-30  8:52 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Fri, Jan 30, 2009 at 01:42:52AM -0700, Paul Walmsley wrote:
> I haven't looked closely at your above three patches for this, but plan to 
> do so later today.
> 
> Regarding provenance, the patches that I sent you were developed 
> independently, for clock notifier support.  Ultimately, I have no personal 
> attachment as to whose patches for this go in, if all technical aspects 
> are equal.

There's one bug that your version highlights in mine - the virtual mpu
clock in omap1 touches the DPLL and repropagates that rate.  I've
removed that repropagation, so that needs fixing.

However, this raises a question: why is the virtual mpu clock touching
some other part of the clock tree.  I wonder whether this should be
handled a different way, though the first thing that needs answering is
why we have this alias for 'arm_ck' ?

^ permalink raw reply	[flat|nested] 50+ messages in thread

* RE: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-30  8:52       ` Russell King - ARM Linux
@ 2009-01-30 14:23         ` Woodruff, Richard
  2009-01-31 11:40           ` Russell King - ARM Linux
  0 siblings, 1 reply; 50+ messages in thread
From: Woodruff, Richard @ 2009-01-30 14:23 UTC (permalink / raw)
  To: Russell King - ARM Linux, Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren


> There's one bug that your version highlights in mine - the virtual mpu
> clock in omap1 touches the DPLL and repropagates that rate.  I've
> removed that repropagation, so that needs fixing.
>
> However, this raises a question: why is the virtual mpu clock touching
> some other part of the clock tree.  I wonder whether this should be
> handled a different way, though the first thing that needs answering is
> why we have this alias for 'arm_ck' ?

At one point in time the virtual clock allowed control for a set of clocks with some dependencies.  The mpu alias provided a convenient control point.

Tukka did original omap1 in this format. I forget its exact meaning.

The original omap2 code had behavior:
        - mpu-dpll had a clock node which allowed direct mpu speed control
        - mpu-virt-clock allowed switching between sets that have fixed ratio dependency which were pegged to current mpu-dll speed.
                * This way round_rate would allow you to discover all valid OPPs.

The first pass OMAP3 code TI did followed omap2 but it wasn't strongly bound by ratio-sets given the multiple async-dplls. Paul has taken code in a bit different direction.  He can comment on current behavior here.

Regards,
Richard W.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-30 14:23         ` Woodruff, Richard
@ 2009-01-31 11:40           ` Russell King - ARM Linux
  2009-02-03  8:42             ` Paul Walmsley
  2009-02-03  9:45             ` Paul Walmsley
  0 siblings, 2 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-01-31 11:40 UTC (permalink / raw)
  To: Woodruff, Richard
  Cc: Paul Walmsley, linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Fri, Jan 30, 2009 at 08:23:49AM -0600, Woodruff, Richard wrote:
> 
> > There's one bug that your version highlights in mine - the virtual mpu
> > clock in omap1 touches the DPLL and repropagates that rate.  I've
> > removed that repropagation, so that needs fixing.
> >
> > However, this raises a question: why is the virtual mpu clock touching
> > some other part of the clock tree.  I wonder whether this should be
> > handled a different way, though the first thing that needs answering is
> > why we have this alias for 'arm_ck' ?
> 
> At one point in time the virtual clock allowed control for a set of clocks
> with some dependencies.  The mpu alias provided a convenient control point.

>From what I can see (checking both mainline and Tony's tree), this mpu
alias (virtual_ck_mpu) is not used on OMAP1, which seems to suggest
that this quirk has become redundant.  If it is redundant, it should
be removed.

If there is some code somewhere to use it, this quirk should live with
the user of the quirk until such time that the user becomes ready to be
merged.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-29 22:06     ` Russell King - ARM Linux
  2009-01-30  8:35       ` Paul Walmsley
@ 2009-02-02  4:57       ` Paul Walmsley
  2009-02-09 14:11       ` Russell King - ARM Linux
  2 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-02  4:57 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell,

On Thu, 29 Jan 2009, Russell King - ARM Linux wrote:

> And here is my version of this patch:

Thanks, your version is quite a bit cleaner than the original.

Will you merge your patch directly, or would you like me to resend your
version here?


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-30  8:42     ` Paul Walmsley
  2009-01-30  8:52       ` Russell King - ARM Linux
@ 2009-02-02  7:13       ` Paul Walmsley
  2009-02-03 13:18         ` Russell King - ARM Linux
  1 sibling, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-02-02  7:13 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell,

On Fri, 30 Jan 2009, Paul Walmsley wrote:

> On Thu, 29 Jan 2009, Russell King - ARM Linux wrote:
> 
> > I must say that this commit looks very much like a combination of
> > my commits from November:
> > 
> > [ARM] omap: move clock propagation into core omap clock code
> > [ARM] omap: remove unnecessary calls to propagate_rate()
> > [ARM] omap: move propagate_rate() calls into generic omap clock code
> > 
> > which do basically the same thing a little more efficiently, and an
> > additional patch from you to call ->recalc after set_rate or
> > reparenting a clock.
> > 
> > So I think I can drop everything from this apart from the additional
> > recalc calls, and the removal of those omap2_dpllcore_recalc() calls.
> > 
> > Please confirm my suspicions.
> 
> I haven't looked closely at your above three patches for this, but plan to 
> do so later today.
> 
> Regarding provenance, the patches that I sent you were developed 
> independently, for clock notifier support.  Ultimately, I have no personal 
> attachment as to whose patches for this go in, if all technical aspects 
> are equal.

Based on a comparison of E 08 with the three omap-clks1 commits you 
mentioned above, here are some differences that would merit further 
attention.  Some of these you've mentioned in subsequent E-mails.

If you use your patches, I would suggest making the following changes:

1. "remove unnecessary calls to propagate_rate()" should keep the 
propagate_rate(&ck_dpll1) call in omap1_select_table_rate(), since this 
function is only used by struct clk virtual_clk_mpu.  virtual_clk_mpu is 
farther away from the root of the clock tree than struct clk ck_dpll1.

2. In plat-omap2/clock.c, clk_set_rate() and clk_set_parent() should call 
propagate_rate() after recalc.

3. Several internal calls to *_recalc() functions can be dropped - 
specifically, in omap2_reprogram_dpllcore(), omap2_select_table_rate(), 
omap3_noncore_dpll_set_rate(), and omap3_core_dpll_m2_set_rate().


If you merge E 08, I'd suggest the following changes:

1. In clock24xx.c:omap2_clk_init(), your patches call propagate_rate() on 
osc_ck and sys_ck immediately after recalcs, which looks like a good 
idea to me.

2. The mach-omap1/clock.c:omap1_clk_init() change to consolidate the two 
propagate_rate(&ck_dpll1) calls also is good.


Please let me know if you'd like any followup patches here.

- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-29 19:52   ` Russell King - ARM Linux
@ 2009-02-02  7:57     ` Paul Walmsley
  0 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-02  7:57 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell,

On Thu, 29 Jan 2009, Russell King - ARM Linux wrote:

> On Wed, Jan 28, 2009 at 12:27:59PM -0700, Paul Walmsley wrote:
> > +static int omap_clk_for_each_child(struct clk *clk, unsigned long parent_rate,
> > +		   u8 rate_storage, int (*cb)(struct clk *, unsigned long, u8))
> > +{
> > +	struct clk_child *child;
> > +	int ret;
> > +
> > +	list_for_each_entry(child, &clk->children, node) {
> > +		ret = (*cb)(child->clk, parent_rate, rate_storage);
> > +		if (ret)
> > +			break;
> > +	}
> > +
> > +	return ret;
> > +}
> 
> > +static int _do_propagate_rate(struct clk *clk, unsigned long parent_rate,
> > +			      u8 rate_storage)
> > +{
> > +	if (clk->recalc)
> > +		clk->recalc(clk, parent_rate, rate_storage);
> > +	if (omap_clk_has_children(clk))
> > +		propagate_rate(clk, rate_storage);
> > +	return 0;
> > +}
> 
> >  /* Propagate rate to children */
> >  void propagate_rate(struct clk *tclk, u8 rate_storage)
> >  {
> >  	unsigned long parent_rate = 0;
> >  
> >  	if (tclk == NULL || IS_ERR(tclk))
> >  		return;
> >  
> > +	if (rate_storage == CURRENT_RATE)
> > +		parent_rate = tclk->rate;
> > +	else if (rate_storage == TEMP_RATE)
> > +		parent_rate = tclk->temp_rate;
> >  
> > +	omap_clk_for_each_child(tclk, parent_rate, rate_storage,
> > +				_do_propagate_rate);
> >  }
> 
> This worries me.  Calling this puts onto the stack:
> 
> - a frame for propagate_rate()
> - a frame for omap_clk_for_each_child
> - a frame for _do_propagate_rate
> 
> for every level of children.  How close we get to overflowing the kernels
> depends on how much each of those functions puts on the kernel stack.
> However, since this is recursive, minimising the number of stack frames
> is a good idea.
> 
> That's why I have in my patch:
> 
>  [ARM] omap: move propagate_rate() calls into generic omap clock code
> 
> I've arranged for there to be the minimum of function nesting here.
> I suggest keeping this.

Those two new function calls are probaby not necessary for rate 
propagation, so, keeping the original single-function recursion should be 
fine.  The original motivation behind using them was to share the clock 
tree traversal code with the clock notifier patches, e.g.,
 
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08068.html

Would you like a patch to remove _do_propagate_rate() and 
omap_clk_for_each_child()?


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-31 11:40           ` Russell King - ARM Linux
@ 2009-02-03  8:42             ` Paul Walmsley
  2009-02-03  9:45             ` Paul Walmsley
  1 sibling, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-03  8:42 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Woodruff, Richard, linux-arm-kernel, linux-kernel, linux-omap,
	Tony Lindgren

Hello Russell, 

On Sat, 31 Jan 2009, Russell King - ARM Linux wrote:

> On Fri, Jan 30, 2009 at 08:23:49AM -0600, Woodruff, Richard wrote:
> > 
> > > There's one bug that your version highlights in mine - the virtual mpu
> > > clock in omap1 touches the DPLL and repropagates that rate.  I've
> > > removed that repropagation, so that needs fixing.
> > >
> > > However, this raises a question: why is the virtual mpu clock touching
> > > some other part of the clock tree.  I wonder whether this should be
> > > handled a different way, though the first thing that needs answering is
> > > why we have this alias for 'arm_ck' ?
> > 
> > At one point in time the virtual clock allowed control for a set of clocks
> > with some dependencies.  The mpu alias provided a convenient control point.
> 
> >From what I can see (checking both mainline and Tony's tree), this mpu
> alias (virtual_ck_mpu) is not used on OMAP1, which seems to suggest
> that this quirk has become redundant.  If it is redundant, it should
> be removed.
>
> If there is some code somewhere to use it, this quirk should live with
> the user of the quirk until such time that the user becomes ready to be
> merged.

I don't think there's any reason for virtual_ck_mpu or virt_prcm_set to 
have a parent clock listed.  

At some point this year, those virtual OPP clocks will be removed from the 
clock tree and implemented in a different manner.

If you like, I will send a patch for removal of virtual_ck_mpu from OMAP1, 
although my suspicion is that OMAP1 is just missing a CPUFreq driver to 
use that OPP clock.


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-01-31 11:40           ` Russell King - ARM Linux
  2009-02-03  8:42             ` Paul Walmsley
@ 2009-02-03  9:45             ` Paul Walmsley
  1 sibling, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-03  9:45 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Woodruff, Richard, linux-arm-kernel, linux-kernel, linux-omap,
	tuukka.tikkanen, Tony Lindgren

Hi Russell,

On Sat, 31 Jan 2009, Russell King - ARM Linux wrote:

> On Fri, Jan 30, 2009 at 08:23:49AM -0600, Woodruff, Richard wrote:
> > 
> > > There's one bug that your version highlights in mine - the virtual mpu
> > > clock in omap1 touches the DPLL and repropagates that rate.  I've
> > > removed that repropagation, so that needs fixing.
> > >
> > > However, this raises a question: why is the virtual mpu clock touching
> > > some other part of the clock tree.  I wonder whether this should be
> > > handled a different way, though the first thing that needs answering is
> > > why we have this alias for 'arm_ck' ?
> > 
> > At one point in time the virtual clock allowed control for a set of clocks
> > with some dependencies.  The mpu alias provided a convenient control point.
> 
> >From what I can see (checking both mainline and Tony's tree), this mpu
> alias (virtual_ck_mpu) is not used on OMAP1, which seems to suggest
> that this quirk has become redundant.  If it is redundant, it should
> be removed.
> 
> If there is some code somewhere to use it, this quirk should live with
> the user of the quirk until such time that the user becomes ready to be
> merged.

It was probably an OMAP1 implementation of OPPs, similar to virt_prcm_set 
on OMAP2.  Looks like the tree is missing a CPUFreq driver that uses it.  
Cc'ing Tuukka in case he recalls.

One fix that might solve your particular problem would be to remove the 
parent clock pointer from virtual_ck_mpu.  Neither virtual_ck_mpu or 
virt_prcm_set should need it.


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c
  2009-02-02  7:13       ` Paul Walmsley
@ 2009-02-03 13:18         ` Russell King - ARM Linux
  0 siblings, 0 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-03 13:18 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Mon, Feb 02, 2009 at 12:13:02AM -0700, Paul Walmsley wrote:
> Based on a comparison of E 08 with the three omap-clks1 commits you 
> mentioned above, here are some differences that would merit further 
> attention.  Some of these you've mentioned in subsequent E-mails.
> 
> If you use your patches, I would suggest making the following changes:
> 
> 1. "remove unnecessary calls to propagate_rate()" should keep the 
> propagate_rate(&ck_dpll1) call in omap1_select_table_rate(), since this 
> function is only used by struct clk virtual_clk_mpu.  virtual_clk_mpu is 
> farther away from the root of the clock tree than struct clk ck_dpll1.

Yes, that's the bug I was talking about in previous mails.  Hence the
follow up questions on why this clock exists.

> 2. In plat-omap2/clock.c, clk_set_rate() and clk_set_parent() should call 
> propagate_rate() after recalc.

If you look at "[ARM] omap: move clock propagation into core omap clock code"
you'll see this is already done after the respective methods are called.
However, in that patch it doesn't call the recalc method; that's a
separate change (see below).

> 3. Several internal calls to *_recalc() functions can be dropped - 
> specifically, in omap2_reprogram_dpllcore(), omap2_select_table_rate(), 
> omap3_noncore_dpll_set_rate(), and omap3_core_dpll_m2_set_rate().

That's what I extracted from and merged as E8:

2d0c7f5596e021f7065511b433d16dd081915a24
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 2ce8c02..4564ae3 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -441,7 +441,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:
@@ -570,7 +569,6 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
 		local_irq_restore(flags);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 06a81fe..75eb254 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -614,8 +614,6 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 	omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n,
 				   freqsel);
 
-	omap3_dpll_recalc(clk);
-
 	return 0;
 }
 
@@ -693,8 +691,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;
 }
 
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 794849b..a166e2a 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -140,8 +140,12 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_rate)
 		ret = arch_clock->clk_set_rate(clk, rate);
-	if (ret == 0 && (clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+	if (ret == 0) {
+		if (clk->recalc)
+			clk->recalc(clk);
+		if (clk->flags & RATE_PROPAGATES)
+			propagate_rate(clk);
+	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -159,8 +163,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_parent)
 		ret = arch_clock->clk_set_parent(clk, parent);
-	if (ret == 0 && (clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+	if (ret == 0) {
+		if (clk->recalc)
+			clk->recalc(clk);
+		if (clk->flags & RATE_PROPAGATES)
+			propagate_rate(clk);
+	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -211,7 +219,7 @@ 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) {
 			unsigned long old_rate = clkp->rate;
 			clkp->recalc(clkp);
 			if (clkp->rate != old_rate &&


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-01-28 19:27 ` [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes Paul Walmsley
@ 2009-02-08 13:17   ` Russell King - ARM Linux
  2009-02-08 19:48     ` David Brownell
  2009-02-11  7:53     ` Paul Walmsley
  2009-02-08 15:53   ` Russell King - ARM Linux
  1 sibling, 2 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-08 13:17 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:27:56PM -0700, Paul Walmsley wrote:
> 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.

NAK.  I'm not sure whether you've realised, but this is exactly what the
'round_rate' method is supposed to be doing.  It provides a method by
which you can find out what the clock rate would be if you asked for
'set_rate' to set the hardware to the requested rate.

A far better way to approach this would be to split the set_rate/recalc
functionality into two parts:

1. a method which returns the both the new clock rate and the hardware
   programming information
2. a method to commit the hardware programming information to the registers

(1) can be used for implementing clk_round_rate() (which is totally lacking
in OMAP2+, yet is implemented in OMAP1), clk_set_rate(), clk_set_parent()
etc.

(2) can be used when it's required to actually reprogram the hardware.

So, rather than the current situation where we have recalc, round_rate
and set_rate methods, we have calc_rate() and commit() methods instead
and have the core clock code sort out calling these.

IOW, clk_set_rate() and clk_round_rate() becomes:

int clk_set_rate(struct clk *clk, unsigned long rate)
{
	unsigned long flags;
	int ret = -EINVAL;

        spin_lock_irqsave(&clockfw_lock, flags);
	if (clk->calc_rate) {
		unsigned long parent_rate = 0;
		struct clk_hw hw;

		if (clk->parent)
			parent_rate = clk->parent->rate;

		ret = clk->calc_rate(clk, parent_rate, &rate, &hw);
		if (ret == 0) {
			clk->rate = rate;
			clk->commit(clk, &hw);
		}
	}
        spin_unlock_irqrestore(&clockfw_lock, flags);

	return ret;
}

long clk_round_rate(struct clk *clk, unsigned long rate)
{
	unsigned long flags;
	long ret;

        spin_lock_irqsave(&clockfw_lock, flags);
	if (clk->calc_rate) {
		unsigned long parent_rate = 0;
		struct clk_hw hw;

		if (clk->parent)
			parent_rate = clk->parent->rate;

		ret = clk->calc_rate(clk, parent_rate, &rate, &hw);
		if (ret == 0)
			ret = rate;
	}
        spin_unlock_irqrestore(&clockfw_lock, flags);

	return ret;
}

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-01-28 19:27 ` [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes Paul Walmsley
  2009-02-08 13:17   ` Russell King - ARM Linux
@ 2009-02-08 15:53   ` Russell King - ARM Linux
  2009-02-11  8:18     ` Paul Walmsley
  1 sibling, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-08 15:53 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:27:56PM -0700, Paul Walmsley wrote:
> 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.

In addition to my previous comments, there's more reason to reject this
patch - it's rather buggy.

> 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.

... the reasoning for this change being?

> diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
> index ae2b304..f3cf6f8 100644
> --- a/arch/arm/mach-omap1/clock.c
> +++ b/arch/arm/mach-omap1/clock.c
> @@ -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;

Ok.

>  }
>  
> -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;

Ok.

>  }
>  
> -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;

This continues to use clk->parent->rate rather than the value passed in.

> +
> +	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;

The above will result in 'temp_rate' not being set if there is no change
in actual clock rate - because of the idiotic caching.  Why is this
idiotic?  Well, think about it for a moment:

        if (clk->rate == clk->parent->rate / dsor)
                return; /* No change, quick exit */
        clk->rate = clk->parent->rate / dsor;

What exactly are we trying to avoid doing here?  The expensive divide?
That divide has to happen in the if statement anyway, so that can't be
it.  Maybe it's trying to avoid the cycles consumed by doing the actual
store?  That's insignificant WRT the divide.

The truth is that nothing significant is being saved by this obscure
complicated code - the only thing that this code is doing is causing
bugs when additional changes happen.

This can all be avoided by moving the assignment of clk->rate out of the
recalc functions and into the caller.  That also eliminates this
rate_storage argument as well, _and_ removes any possibility of broken
"caching" code surviving since it forces you to always return the rate
you intend from the function.

See the bottom of this mail for the first step to implement this.

>  }
>  
> -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 */

More buggy caching.

> -	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,
> diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
> index 43f6ce8..df94ad6 100644
> --- a/arch/arm/mach-omap1/clock.h
> +++ b/arch/arm/mach-omap1/clock.h
> @@ -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);
> diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
> index 4a72535..0c00706 100644
> --- a/arch/arm/mach-omap2/clock.c
> +++ b/arch/arm/mach-omap2/clock.c
> @@ -240,6 +240,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
> @@ -251,7 +252,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;
> @@ -269,7 +270,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()) {
>  
> @@ -285,7 +286,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;
> @@ -295,11 +296,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;

Ok.

>  }
>  
>  /**
> @@ -486,9 +495,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);
>  
> @@ -496,9 +507,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;

Thankfully you remove the buggy caching here.

>  
>  	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
>  }
> diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
> index faff95e..a026ec9 100644
> --- a/arch/arm/mach-omap2/clock.h
> +++ b/arch/arm/mach-omap2/clock.h
> @@ -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);
> diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
> index 57cd85b..cd9fa0d 100644
> --- a/arch/arm/mach-omap2/clock24xx.c
> +++ b/arch/arm/mach-omap2/clock24xx.c
> @@ -64,6 +64,7 @@ static struct clk *sclk;
>  /**
>   * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
>   * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
> + * @parent_rate: rate of the parent of the dpll_ck
>   *
>   * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
>   * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
> @@ -71,12 +72,13 @@ static struct clk *sclk;
>   * struct clk *dpll_ck, which is a composite clock of dpll_ck and
>   * core_ck.
>   */
> -static u32 omap2xxx_clk_get_core_rate(struct clk *clk)
> +static u32 omap2xxx_clk_get_core_rate(struct clk *clk,
> +				      unsigned long parent_rate)
>  {
>  	long long core_clk;
>  	u32 v;
>  
> -	core_clk = omap2_get_dpll_rate(clk);
> +	core_clk = omap2_get_dpll_rate(clk, parent_rate);
>  
>  	v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
>  	v &= OMAP24XX_CORE_CLK_SRC_MASK;
> @@ -89,6 +91,30 @@ static u32 omap2xxx_clk_get_core_rate(struct clk *clk)
>  	return core_clk;
>  }
>  
> +static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed,
> +							 struct prcm_config **prcm)
> +{
> +	unsigned long found_speed = 0;
> +	struct prcm_config *p;
> +
> +	p = *prcm;
> +
> +	for (p = rate_table; p->mpu_speed; p++) {
> +		if (!(p->flags & cpu_mask))
> +			continue;
> +
> +		if (p->xtal_speed != sys_ck.rate)
> +			continue;
> +
> +		if (p->mpu_speed <= mpu_speed) {
> +			found_speed = p->mpu_speed;
> +			break;
> +		}
> +	}
> +
> +	return found_speed;
> +}
> +

This looks like a change of functionality in this patch.

>  static int omap2_enable_osc_ck(struct clk *clk)
>  {
>  	prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, 0,
> @@ -176,9 +202,17 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
>  
>  }
>  
> -static void omap2_dpllcore_recalc(struct clk *clk)
> +static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate,
> +				  u8 rate_storage)
>  {
> -	clk->rate = omap2xxx_clk_get_core_rate(clk);
> +	unsigned long rate;
> +
> +	rate = omap2xxx_clk_get_core_rate(clk, parent_rate);
> +
> +	if (rate_storage == CURRENT_RATE)
> +		clk->rate = rate;
> +	else if (rate_storage == TEMP_RATE)
> +		clk->temp_rate = rate;

Assuming it still works, ok.

>  }
>  
>  static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
> @@ -191,7 +225,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
>  	int ret = -EINVAL;
>  
>  	local_irq_save(flags);
> -	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
> +	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;
>  
> @@ -262,9 +296,18 @@ dpll_exit:
>   *
>   * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
>   */
> -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)
>  {
> -	clk->rate = curr_prcm_set->mpu_speed;
> +	struct prcm_config *prcm;
> +	unsigned long mpurate;
> +
> +	mpurate = omap2xxx_clk_find_oppset_by_mpurate(parent_rate, &prcm);
> +
> +	if (rate_storage == CURRENT_RATE)
> +		clk->rate = mpurate;
> +	else if (rate_storage == TEMP_RATE)
> +		clk->temp_rate = mpurate;

Assuming it still works, ok.

>  }
>  
>  /*
> @@ -304,25 +347,12 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
>  {
>  	u32 cur_rate, done_rate, bypass = 0, tmp;
>  	struct prcm_config *prcm;
> -	unsigned long found_speed = 0;
> -	unsigned long flags;
> +	unsigned long flags, found_speed;
>  
>  	if (clk != &virt_prcm_set)
>  		return -EINVAL;
>  
> -	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
> -		if (!(prcm->flags & cpu_mask))
> -			continue;
> -
> -		if (prcm->xtal_speed != sys_ck.rate)
> -			continue;
> -
> -		if (prcm->mpu_speed <= rate) {
> -			found_speed = prcm->mpu_speed;
> -			break;
> -		}
> -	}
> -
> +	found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm);
>  	if (!found_speed) {
>  		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
>  		       rate / 1000000);
> @@ -330,7 +360,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
>  	}
>  
>  	curr_prcm_set = prcm;
> -	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
> +	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
>  
>  	if (prcm->dpll_speed == cur_rate / 2) {
>  		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
> @@ -463,14 +493,31 @@ static u32 omap2_get_sysclkdiv(void)
>  	return div;
>  }
>  
> -static void omap2_osc_clk_recalc(struct clk *clk)
> +static void omap2_osc_clk_recalc(struct clk *clk, unsigned long parent_rate,
> +				 u8 rate_storage)
>  {
> -	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
> +	unsigned long rate;
> +
> +	/* XXX osc_ck on 2xxx currently is parentless */
> +	rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
> +
> +	if (rate_storage == CURRENT_RATE)
> +		clk->rate = rate;
> +	else if (rate_storage == TEMP_RATE)
> +		clk->temp_rate = rate;

Ok.

>  }
>  
> -static void omap2_sys_clk_recalc(struct clk *clk)
> +static void omap2_sys_clk_recalc(struct clk *clk, unsigned long parent_rate,
> +				 u8 rate_storage)
>  {
> -	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
> +	unsigned long rate;
> +
> +	rate = parent_rate / omap2_get_sysclkdiv();
> +
> +	if (rate_storage == CURRENT_RATE)
> +		clk->rate = rate;
> +	else if (rate_storage == TEMP_RATE)
> +		clk->temp_rate = rate;

Ok.

>  }
>  
>  /*
> @@ -523,8 +570,8 @@ int __init omap2_clk_init(void)
>  
>  	clk_init(&omap2_clk_functions);
>  
> -	omap2_osc_clk_recalc(&osc_ck);
> -	omap2_sys_clk_recalc(&sys_ck);
> +	omap2_osc_clk_recalc(&osc_ck, 0, CURRENT_RATE);
> +	omap2_sys_clk_recalc(&sys_ck, sys_ck.parent->rate, CURRENT_RATE);
>  
>  	for (clkp = onchip_24xx_clks;
>  	     clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
> @@ -544,7 +591,7 @@ int __init omap2_clk_init(void)
>  	}
>  
>  	/* Check the MPU rate set by bootloader */
> -	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
> +	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
>  	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
>  		if (!(prcm->flags & cpu_mask))
>  			continue;
> diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
> index 30f3c57..cd9feda 100644
> --- a/arch/arm/mach-omap2/clock24xx.h
> +++ b/arch/arm/mach-omap2/clock24xx.h
> @@ -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);
> diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
> index 22cbcce..917664d 100644
> --- a/arch/arm/mach-omap2/clock34xx.c
> +++ b/arch/arm/mach-omap2/clock34xx.c
> @@ -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;

Ok.

>  }
>  
>  /* _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;

Ok.

>  }
>  
>  /* Common clock code */
> diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
> index 66cbe0c..283c386 100644
> --- a/arch/arm/mach-omap2/clock34xx.h
> +++ b/arch/arm/mach-omap2/clock34xx.h
> @@ -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,
> diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
> index 4cf1145..7a7547d 100644
> --- a/arch/arm/plat-omap/clock.c
> +++ b/arch/arm/plat-omap/clock.c
> @@ -83,8 +83,17 @@ int clk_enable(struct clk *clk)
>  		return -EINVAL;
>  
>  	spin_lock_irqsave(&clockfw_lock, flags);
> -	if (arch_clock->clk_enable)
> +	if (arch_clock->clk_enable) {
>  		ret = arch_clock->clk_enable(clk);
> +		if (ret == 0 && clk->flags & RECALC_ON_ENABLE) {
> +			if (clk->recalc)
> +				(*clk->recalc)(clk, clk->parent->rate,
> +					       CURRENT_RATE);
> +			if (clk->flags & RATE_PROPAGATES)
> +				propagate_rate(clk, CURRENT_RATE);
> +		}
> +	}
> +
>  	spin_unlock_irqrestore(&clockfw_lock, flags);
>  
>  	return ret;
> @@ -106,8 +115,16 @@ void clk_disable(struct clk *clk)
>  		goto out;
>  	}
>  
> -	if (arch_clock->clk_disable)
> +	if (arch_clock->clk_disable) {
>  		arch_clock->clk_disable(clk);
> +		if (clk->flags & RECALC_ON_ENABLE) {
> +			if (clk->recalc)
> +				(*clk->recalc)(clk, clk->parent->rate,
> +					       CURRENT_RATE);
> +			if (clk->flags & RATE_PROPAGATES)
> +				propagate_rate(clk, CURRENT_RATE);
> +		}
> +	}
>  
>  out:
>  	spin_unlock_irqrestore(&clockfw_lock, flags);
> @@ -188,9 +205,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
>  		ret = arch_clock->clk_set_rate(clk, rate);
>  		if (ret == 0) {
>  			if (clk->recalc)
> -				(*clk->recalc)(clk);
> +				(*clk->recalc)(clk, clk->parent->rate,
> +					       CURRENT_RATE);
>  			if (clk->flags & RATE_PROPAGATES)
> -				propagate_rate(clk);
> +				propagate_rate(clk, CURRENT_RATE);
>  		}
>  	}
>  
> @@ -214,9 +232,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
>  		ret = arch_clock->clk_set_parent(clk, parent);
>  		if (ret == 0) {
>  			if (clk->recalc)
> -				(*clk->recalc)(clk);
> +				(*clk->recalc)(clk, clk->parent->rate,
> +					       CURRENT_RATE);
>  			if (clk->flags & RATE_PROPAGATES)
> -				propagate_rate(clk);
> +				propagate_rate(clk, CURRENT_RATE);
>  		}
>  	}
>  
> @@ -268,18 +287,20 @@ static int __init omap_clk_setup(char *str)
>  __setup("mpurate=", omap_clk_setup);
>  
>  /* Used for clocks that always have same value as the parent clock */
> -void followparent_recalc(struct clk *clk)
> +void followparent_recalc(struct clk *clk, unsigned long new_parent_rate,
> +			 u8 rate_storage)
>  {
> -	if (clk == NULL || IS_ERR(clk))
> -		return;
> -
> -	clk->rate = clk->parent->rate;
> +	if (rate_storage == CURRENT_RATE)
> +		clk->rate = new_parent_rate;
> +	else if (rate_storage == TEMP_RATE)
> +		clk->temp_rate = new_parent_rate;

Ok.

Here's the implementation of the recalc method returning the new rate.
As you can see, it moves the business of where we store it completely
out of the recalc implementation code, which would make the implementation
of the 'temp_rate' solution a whole lot smaller.

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 33794cd..758a3a3 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -156,27 +156,27 @@ __u32 arm_idlect1_mask;
  * Omap1 specific clock functions
  *-------------------------------------------------------------------------*/
 
-static void omap1_watchdog_recalc(struct clk * clk)
+static unsigned long omap1_watchdog_recalc(struct clk * clk)
 {
-	clk->rate = clk->parent->rate / 14;
+	return clk->parent->rate / 14;
 }
 
-static void omap1_uart_recalc(struct clk * clk)
+static unsigned long omap1_uart_recalc(struct clk * clk)
 {
 	unsigned int val = __raw_readl(clk->enable_reg);
 	if (val & clk->enable_bit)
-		clk->rate = 48000000;
+		return 48000000;
 	else
-		clk->rate = 12000000;
+		return 12000000;
 }
 
-static void omap1_sossi_recalc(struct clk *clk)
+static unsigned long omap1_sossi_recalc(struct clk *clk)
 {
 	u32 div = omap_readl(MOD_CONF_CTRL_1);
 
 	div = (div >> 17) & 0x7;
 	div++;
-	clk->rate = clk->parent->rate / div;
+	return clk->parent->rate / div;
 }
 
 static int omap1_clk_enable_dsp_domain(struct clk *clk)
@@ -347,19 +347,15 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate)
 	return dsor_exp;
 }
 
-static void omap1_ckctl_recalc(struct clk * clk)
+static unsigned long omap1_ckctl_recalc(struct clk * clk)
 {
-	int dsor;
-
 	/* Calculate divisor encoded as 2-bit exponent */
-	dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
+	int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
 
-	if (unlikely(clk->rate == clk->parent->rate / dsor))
-		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
+	return clk->parent->rate / dsor;
 }
 
-static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
+static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk * clk)
 {
 	int dsor;
 
@@ -374,9 +370,7 @@ 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))
-		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
+	return clk->parent->rate / dsor;
 }
 
 /* MPU virtual clock functions */
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index cb7c7fb..2b9aec0 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -13,14 +13,14 @@
 #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
 #define __ARCH_ARM_MACH_OMAP1_CLOCK_H
 
-static void omap1_ckctl_recalc(struct clk * clk);
-static void omap1_watchdog_recalc(struct clk * clk);
+static unsigned long omap1_ckctl_recalc(struct clk * clk);
+static unsigned long omap1_watchdog_recalc(struct clk * clk);
 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 unsigned long omap1_sossi_recalc(struct clk *clk);
+static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk * clk);
 static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate);
 static int omap1_set_uart_rate(struct clk * clk, unsigned long rate);
-static void omap1_uart_recalc(struct clk * clk);
+static unsigned long omap1_uart_recalc(struct clk * clk);
 static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate);
 static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate);
 static void omap1_init_ext_clk(struct clk * clk);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 1b40d75..5020cb1 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -239,11 +239,11 @@ 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)
+unsigned long omap2_fixed_divisor_recalc(struct clk *clk)
 {
 	WARN_ON(!clk->fixed_div);
 
-	clk->rate = clk->parent->rate / clk->fixed_div;
+	return clk->parent->rate / clk->fixed_div;
 }
 
 /**
@@ -449,21 +449,22 @@ err:
  * 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)
+unsigned long omap2_clksel_recalc(struct clk *clk)
 {
+	unsigned long rate;
 	u32 div = 0;
 
 	pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
 
 	div = omap2_clksel_get_divisor(clk);
 	if (div == 0)
-		return;
+		return clk->rate;
 
-	if (clk->rate == (clk->parent->rate / div))
-		return;
-	clk->rate = clk->parent->rate / div;
+	rate = clk->parent->rate / div;
+
+	pr_debug("clock: new clock rate is %ld (div %d)\n", rate, div);
 
-	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+	return rate;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 90077f0..ca6bf22 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -36,7 +36,7 @@ void omap2_clk_disable_unused(struct clk *clk);
 #define omap2_clk_disable_unused	NULL
 #endif
 
-void omap2_clksel_recalc(struct clk *clk);
+unsigned long omap2_clksel_recalc(struct clk *clk);
 void omap2_init_clk_clkdm(struct clk *clk);
 void omap2_init_clksel_parent(struct clk *clk);
 u32 omap2_clksel_get_divisor(struct clk *clk);
@@ -44,7 +44,7 @@ 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);
+unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 u32 omap2_get_dpll_rate(struct clk *clk);
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 069f3e1..f2b74e9 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -369,9 +369,9 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 
 }
 
-static void omap2_dpllcore_recalc(struct clk *clk)
+static unsigned long omap2_dpllcore_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_dpll_rate_24xx(clk);
+	return omap2_get_dpll_rate_24xx(clk);
 }
 
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
@@ -448,9 +448,9 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
  *
  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
  */
-static void omap2_table_mpu_recalc(struct clk *clk)
+static unsigned long omap2_table_mpu_recalc(struct clk *clk)
 {
-	clk->rate = curr_prcm_set->mpu_speed;
+	return curr_prcm_set->mpu_speed;
 }
 
 /*
@@ -647,14 +647,14 @@ static u32 omap2_get_sysclkdiv(void)
 	return div;
 }
 
-static void omap2_osc_clk_recalc(struct clk *clk)
+static unsigned long omap2_osc_clk_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
+	return omap2_get_apll_clkin() * omap2_get_sysclkdiv();
 }
 
-static void omap2_sys_clk_recalc(struct clk *clk)
+static unsigned long omap2_sys_clk_recalc(struct clk *clk)
 {
-	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
+	return clk->parent->rate / omap2_get_sysclkdiv();
 }
 
 /*
@@ -707,9 +707,9 @@ int __init omap2_clk_init(void)
 
 	clk_init(&omap2_clk_functions);
 
-	omap2_osc_clk_recalc(&osc_ck);
+	osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
 	propagate_rate(&osc_ck);
-	omap2_sys_clk_recalc(&sys_ck);
+	sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
 	propagate_rate(&sys_ck);
 
 	for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 7594898..11da621 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -24,13 +24,13 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 
-static void omap2_table_mpu_recalc(struct clk *clk);
+static unsigned long omap2_table_mpu_recalc(struct clk *clk);
 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 unsigned long omap2_sys_clk_recalc(struct clk *clk);
+static unsigned long omap2_osc_clk_recalc(struct clk *clk);
+static unsigned long omap2_sys_clk_recalc(struct clk *clk);
+static unsigned long omap2_dpllcore_recalc(struct clk *clk);
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
 
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 3b6e27b..fb0f53b 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -289,9 +289,9 @@ static struct omap_clk omap34xx_clks[] = {
  *
  * Recalculate and propagate the DPLL rate.
  */
-static void omap3_dpll_recalc(struct clk *clk)
+static unsigned long omap3_dpll_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_dpll_rate(clk);
+	return omap2_get_dpll_rate(clk);
 }
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -787,9 +787,10 @@ static void omap3_dpll_deny_idle(struct clk *clk)
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
-static void omap3_clkoutx2_recalc(struct clk *clk)
+static unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 {
 	const struct dpll_data *dd;
+	unsigned long rate;
 	u32 v;
 	struct clk *pclk;
 
@@ -808,9 +809,10 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
 	v = __raw_readl(dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 	if (v != DPLL_LOCKED)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = clk->parent->rate * 2;
+		rate = clk->parent->rate * 2;
+	return rate;
 }
 
 /* Common clock code */
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 2138a58..764c7cd 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -27,8 +27,8 @@
 #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 unsigned long omap3_dpll_recalc(struct clk *clk);
+static unsigned long omap3_clkoutx2_recalc(struct clk *clk);
 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);
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 8a2d566..78819d0 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -126,7 +126,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 		ret = arch_clock->clk_set_rate(clk, rate);
 	if (ret == 0) {
 		if (clk->recalc)
-			clk->recalc(clk);
+			clk->rate = clk->recalc(clk);
 		propagate_rate(clk);
 	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -148,7 +148,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 		ret = arch_clock->clk_set_parent(clk, parent);
 	if (ret == 0) {
 		if (clk->recalc)
-			clk->recalc(clk);
+			clk->rate = clk->recalc(clk);
 		propagate_rate(clk);
 	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -182,12 +182,9 @@ static int __init omap_clk_setup(char *str)
 __setup("mpurate=", omap_clk_setup);
 
 /* Used for clocks that always have same value as the parent clock */
-void followparent_recalc(struct clk *clk)
+unsigned long followparent_recalc(struct clk *clk)
 {
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	clk->rate = clk->parent->rate;
+	return clk->parent->rate;
 }
 
 void clk_reparent(struct clk *child, struct clk *parent)
@@ -208,7 +205,7 @@ void propagate_rate(struct clk * tclk)
 
 	list_for_each_entry(clkp, &tclk->children, sibling) {
 		if (clkp->recalc)
-			clkp->recalc(clkp);
+			clkp->rate = clkp->recalc(clkp);
 		propagate_rate(clkp);
 	}
 }
@@ -228,7 +225,7 @@ void recalculate_root_clocks(void)
 
 	list_for_each_entry(clkp, &root_clks, sibling) {
 		if (clkp->recalc)
-			clkp->recalc(clkp);
+			clkp->rate = clkp->recalc(clkp);
 		propagate_rate(clkp);
 	}
 }
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index ac9a8ae..3e1b0ab 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -75,7 +75,7 @@ struct clk {
 	unsigned long		rate;
 	__u32			flags;
 	void __iomem		*enable_reg;
-	void			(*recalc)(struct clk *);
+	unsigned long		(*recalc)(struct clk *);
 	int			(*set_rate)(struct clk *, unsigned long);
 	long			(*round_rate)(struct clk *, unsigned long);
 	void			(*init)(struct clk *);
@@ -123,7 +123,7 @@ extern void clk_reparent(struct clk *child, struct clk *parent);
 extern void clk_unregister(struct clk *clk);
 extern void propagate_rate(struct clk *clk);
 extern void recalculate_root_clocks(void);
-extern void followparent_recalc(struct clk *clk);
+extern unsigned long followparent_recalc(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);

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-02-08 13:17   ` Russell King - ARM Linux
@ 2009-02-08 19:48     ` David Brownell
  2009-02-11  7:53     ` Paul Walmsley
  1 sibling, 0 replies; 50+ messages in thread
From: David Brownell @ 2009-02-08 19:48 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Paul Walmsley, linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Sunday 08 February 2009, Russell King - ARM Linux wrote:
> A far better way to approach this would be to split the set_rate/recalc
> functionality into two parts:
> 
> 1. a method which returns the both the new clock rate and the hardware
>    programming information
> 2. a method to commit the hardware programming information to the registers

Much simpler to just pass a "commit" flag and not
try to come up with some generic way to represent
"hardware programming information"; in general that
will be very different between clocks.

Then clk_round_rate() passes "false" for commit,
while clk_set_rate() passes "true".  And in both
cases the value returned is the rate, or negative
errno to indicate a fault.

- Dave

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-01-29 22:06     ` Russell King - ARM Linux
  2009-01-30  8:35       ` Paul Walmsley
  2009-02-02  4:57       ` Paul Walmsley
@ 2009-02-09 14:11       ` Russell King - ARM Linux
  2009-02-13  7:01         ` Paul Walmsley
  2 siblings, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-09 14:11 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Thu, Jan 29, 2009 at 10:06:08PM +0000, Russell King - ARM Linux wrote:
> @@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
>  	if (clk->usecount > 0)
>  		_omap2_clk_enable(clk);
>  
> -	clk->parent = new_parent;
> +	clk_reparent(clk, new_parent);

While looking at the DPLL patches, I've realised that omap2_clk_set_parent()
is buggy, as are any other places which reparent the clock (thankfully
the only other place is in the initialisation code where it doesn't
matter.)

Consider what happens when a clock is enabled - we walk up the tree
enabling all parents.  If we then change the clock's parent, and
then disable the child, we will again walk up the tree, but since
we've reparented it, it will be a different clock tree.  The result
is that the ancestors clock usage counts, and therefore their enable
status, will end up getting screwed up.

So, this has revealed a logical bug here.  We need to walk the
parent tree before and after the switch to ensure that things stay
sane.

This brings up a question: what we currently do here is:

- disable the child
- program clksel
- enable the child
- change child->parent

If we add in the parent handling, there are two possibilities:

- disable the child
- enable the new parent tree
- program clksel
- change child->parent
- disable the old parent tree
- enable the child

OR

- disable the child and the old parent tree
- program clksel
- change child->parent
- enable the new parent tree and the child

(note those 'and's have implied ordering).

Is there anything which dictates one approach over the other?
Obviously the latter approach results in something smaller and
cleaner, but might not be technically correct.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-02-08 13:17   ` Russell King - ARM Linux
  2009-02-08 19:48     ` David Brownell
@ 2009-02-11  7:53     ` Paul Walmsley
  1 sibling, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-11  7:53 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell,

On Sun, 8 Feb 2009, Russell King - ARM Linux wrote:

> On Wed, Jan 28, 2009 at 12:27:56PM -0700, Paul Walmsley wrote:
> > 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.
> 
> NAK.  I'm not sure whether you've realised, but this is exactly what the
> 'round_rate' method is supposed to be doing.  It provides a method by
> which you can find out what the clock rate would be if you asked for
> 'set_rate' to set the hardware to the requested rate.

There's been some miscommunication about the purpose of this patch - most 
likely my fault for not grouping this patch with the clock notifier patch 
set, which has not yet been submitted for upstream merging.  Most of this 
patch is not needed until notifiers are implemented, so I'd propose that 
we defer consideration of most of this patch until the clock notifiers are 
submitted.  What would be useful, though, is to split out the 
RECALC_ON_ENABLE portion of this patch and merge that.  That is a bug fix, 
and I should have sent that as a separate patch.

For the sake of the current discussion though, here's what this patch was 
intended to accomplish.  We have some patches under development that 
implement clock rate change notifiers, allowing drivers to register for 
pre- and post-notification on clock rate changes.  The notifier callbacks 
are passed the old clock rate and the new clock rate.  Since a rate change 
on a clock in the middle of the clock tree (e.g., dpll3_m2_ck) can affect 
all clocks downstream, the clock code must compute the new rate for not 
only dpll3_m2_ck, but also all downstream clocks, before clk->rate is 
updated and the hardware registers are actually changed.

This presents a problem with the current code.  Consider the 
pre-notification case, in which the clock code needs to compute the target 
clock rate without actually updating clk->rate.  But the round_rate() 
functions assume that the parent clock's current rate is what should be 
used.  If the parent clock's rate would also change as part of the 
clk_set_rate(), the target rate computation will return an incorrect rate.

So this patch allows temporary rates to be computed for all of the clocks 
that would be affected by the rate or parent change, so the correct target 
rates can be passed to each clock's notifier (assuming one exists for the 
clock).

N.B., this temporary rate computation is also the motivation behind the 
recursive propagate_rate() calls that we discussed earlier.

It also may turn out that it's unnecessary to pass the new rate to the 
notifiers, in which case most of this code won't need to reappear.

> A far better way to approach this would be to split the set_rate/recalc
> functionality into two parts:
> 
> 1. a method which returns the both the new clock rate and the hardware
>    programming information
> 2. a method to commit the hardware programming information to the registers
> 
> (1) can be used for implementing clk_round_rate() (which is totally lacking
> in OMAP2+, yet is implemented in OMAP1), clk_set_rate(), clk_set_parent()
> etc.

The OMAP2/3 clock code does implement clk_round_rate() - most commonly via 
mach-omap2/clock.c:omap2_clksel_round_rate().  There are a few special 
cases which use other round_rate() functions.

> (2) can be used when it's required to actually reprogram the hardware.
> 
> So, rather than the current situation where we have recalc, round_rate
> and set_rate methods, we have calc_rate() and commit() methods instead
> and have the core clock code sort out calling these.

I haven't yet spent much time thinking about this new arrangement -- it 
seems to be orthogonal to the problem that this patch is intended to solve 
-- but it might make sense for a different purpose.  Many of our 
set_rate() functions wind up calling round_rate() first to determine 
whether the passed-in rate is valid and to return the hardware programming 
data from the clksel structures.  This extra call to round_rate() just 
wastes cycles.  So this new layout might be more efficient, although it 
appears that calc_rate() is called twice in the new arrangement as well.


I appreciate the ongoing technical review,

- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes
  2009-02-08 15:53   ` Russell King - ARM Linux
@ 2009-02-11  8:18     ` Paul Walmsley
  0 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-11  8:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hello Russell,

On Sun, 8 Feb 2009, Russell King - ARM Linux wrote:

> On Wed, Jan 28, 2009 at 12:27:56PM -0700, Paul Walmsley wrote:
> > 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.
> 
> In addition to my previous comments, there's more reason to reject this
> patch - it's rather buggy.
> 
> > 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.
> 
> ... the reasoning for this change being?

For most clocks in the clock tree, there's no need to recalculate the 
clock rate and the downstream clock rates when the clock is enabled 
or disabled.  clk->rate is not adjusted; the rate is simply considered to 
be 0 if the clock is disabled.

There is one type of OMAP clock, though, that this may not hold true for: 
DPLLs.  Currently, the "disabled" state for DPLLs can mean one of two 
general modes: stop (in which the DPLL output rate is zero), or bypass (in 
which the DPLL output rate is the bypass clock rate).  RECALC_ON_ENABLE is 
intended to fix the latter case.  

As we've discussed before, this may be better implemented as a reparent 
operation; but there is a twist: DPLLs can autoidle (if programmed to do 
so).  In this case the DPLL is considered to be enabled, but is actually 
emitting a bypass rate or is stopped.  The OMAP hardware automatically 
restarts the DPLL when a downstream clock is enabled, with no notification 
to the operating system.  So some type of RECALC_ON_ENABLE logic may need 
to stay.

> > diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
> > index ae2b304..f3cf6f8 100644
> > --- a/arch/arm/mach-omap1/clock.c
> > +++ b/arch/arm/mach-omap1/clock.c
> >  
> > -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;
> 
> This continues to use clk->parent->rate rather than the value passed in.

Indeed, this should be fixed.

> > @@ -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;
> 
> The above will result in 'temp_rate' not being set if there is no change
> in actual clock rate

Indeed, this also needs to be fixed.

> This can all be avoided by moving the assignment of clk->rate out of the
> recalc functions and into the caller.  That also eliminates this
> rate_storage argument as well, _and_ removes any possibility of broken
> "caching" code surviving since it forces you to always return the rate
> you intend from the function.
> 
> See the bottom of this mail for the first step to implement this.
> 
> > @@ -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 */
> 
> More buggy caching.

Yep.

> > diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
> > index 57cd85b..cd9fa0d 100644
> > --- a/arch/arm/mach-omap2/clock24xx.c
> > +++ b/arch/arm/mach-omap2/clock24xx.c
> > @@ -89,6 +91,30 @@ static u32 omap2xxx_clk_get_core_rate(struct clk *clk)
> >  	return core_clk;
> >  }
> >  
> > +static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed,
> > +							 struct prcm_config **prcm)
> > +{
> > +	unsigned long found_speed = 0;
> > +	struct prcm_config *p;
> > +
> > +	p = *prcm;
> > +
> > +	for (p = rate_table; p->mpu_speed; p++) {
> > +		if (!(p->flags & cpu_mask))
> > +			continue;
> > +
> > +		if (p->xtal_speed != sys_ck.rate)
> > +			continue;
> > +
> > +		if (p->mpu_speed <= mpu_speed) {
> > +			found_speed = p->mpu_speed;
> > +			break;
> > +		}
> > +	}
> > +
> > +	return found_speed;
> > +}
> > +
> 
> This looks like a change of functionality in this patch.

The goal of this part of the change was to eliminate some duplicate code.  
This rate_table walk had previously existed in several other places in the 
code with minor variations; the intention here was to combine those into a 
common function.

> Here's the implementation of the recalc method returning the new rate.
> As you can see, it moves the business of where we store it completely
> out of the recalc implementation code, which would make the implementation
> of the 'temp_rate' solution a whole lot smaller.

I'm happy with this change - it looks good to me,


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-09 14:11       ` Russell King - ARM Linux
@ 2009-02-13  7:01         ` Paul Walmsley
  2009-02-14 11:23           ` Russell King - ARM Linux
  0 siblings, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-02-13  7:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

(cc'ing Richard Woodruff)

Hello Russell,

On Mon, 9 Feb 2009, Russell King - ARM Linux wrote:

> On Thu, Jan 29, 2009 at 10:06:08PM +0000, Russell King - ARM Linux wrote:
> > @@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
> >  	if (clk->usecount > 0)
> >  		_omap2_clk_enable(clk);
> >  
> > -	clk->parent = new_parent;
> > +	clk_reparent(clk, new_parent);
> 
> While looking at the DPLL patches, I've realised that omap2_clk_set_parent()
> is buggy, as are any other places which reparent the clock (thankfully
> the only other place is in the initialisation code where it doesn't
> matter.)
> 
> Consider what happens when a clock is enabled - we walk up the tree
> enabling all parents.  If we then change the clock's parent, and
> then disable the child, we will again walk up the tree, but since
> we've reparented it, it will be a different clock tree.  The result
> is that the ancestors clock usage counts, and therefore their enable
> status, will end up getting screwed up.

Agreed.

> This brings up a question: what we currently do here is:
> 
> - disable the child
> - program clksel
> - enable the child
> - change child->parent
> 
> If we add in the parent handling, there are two possibilities:
> 
> - disable the child
> - enable the new parent tree
> - program clksel
> - change child->parent
> - disable the old parent tree
> - enable the child
> 
> OR
> 
> - disable the child and the old parent tree
> - program clksel
> - change child->parent
> - enable the new parent tree and the child
> 
> (note those 'and's have implied ordering).
> 
> Is there anything which dictates one approach over the other?
> Obviously the latter approach results in something smaller and
> cleaner, but might not be technically correct.

I don't know of any hardware reason to prefer one approach over the other, 
but Richard might know better.


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-13  7:01         ` Paul Walmsley
@ 2009-02-14 11:23           ` Russell King - ARM Linux
  2009-02-14 11:36             ` Russell King - ARM Linux
                               ` (2 more replies)
  0 siblings, 3 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-14 11:23 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

On Fri, Feb 13, 2009 at 12:01:37AM -0700, Paul Walmsley wrote:
> (cc'ing Richard Woodruff)
> 
> Hello Russell,
> 
> On Mon, 9 Feb 2009, Russell King - ARM Linux wrote:
> 
> > On Thu, Jan 29, 2009 at 10:06:08PM +0000, Russell King - ARM Linux wrote:
> > > @@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
> > >  	if (clk->usecount > 0)
> > >  		_omap2_clk_enable(clk);
> > >  
> > > -	clk->parent = new_parent;
> > > +	clk_reparent(clk, new_parent);
> > 
> > While looking at the DPLL patches, I've realised that omap2_clk_set_parent()
> > is buggy, as are any other places which reparent the clock (thankfully
> > the only other place is in the initialisation code where it doesn't
> > matter.)
> > 
> > Consider what happens when a clock is enabled - we walk up the tree
> > enabling all parents.  If we then change the clock's parent, and
> > then disable the child, we will again walk up the tree, but since
> > we've reparented it, it will be a different clock tree.  The result
> > is that the ancestors clock usage counts, and therefore their enable
> > status, will end up getting screwed up.
> 
> Agreed.
> 
> > This brings up a question: what we currently do here is:
> > 
> > - disable the child
> > - program clksel
> > - enable the child
> > - change child->parent
> > 
> > If we add in the parent handling, there are two possibilities:
> > 
> > - disable the child
> > - enable the new parent tree
> > - program clksel
> > - change child->parent
> > - disable the old parent tree
> > - enable the child
> > 
> > OR
> > 
> > - disable the child and the old parent tree
> > - program clksel
> > - change child->parent
> > - enable the new parent tree and the child
> > 
> > (note those 'and's have implied ordering).
> > 
> > Is there anything which dictates one approach over the other?
> > Obviously the latter approach results in something smaller and
> > cleaner, but might not be technically correct.
> 
> I don't know of any hardware reason to prefer one approach over the other, 
> but Richard might know better.

I'll need an answer on this before I can commit the updated bypass clock
support patch.

However, looking a little deeper, there's more issues in the reparenting
area.  I don't think this code has been tested at all...  In
_omap2_clksel_get_src_field, there is this:

	for (clkr = clks->rates; clkr->div; clkr++) {
		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
			break; /* Found the default rate for this platform */
	}

which is bogus - it will find the first entry which is _either_ marked
as a default rate _or_ is supported by the SoC.  This means (for
instance) that:

static const struct clksel_rate core_l3_core_rates[] = {
        { .div = 1, .val = 1, .flags = RATE_IN_24XX },
        { .div = 2, .val = 2, .flags = RATE_IN_242X },
        { .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },

will give us divisor 1 rather than presumably the one we want, that being
divisor 4.  I think the test above should be:

	for (clkr = clks->rates; clkr->div; clkr++) {
		if (clkr->flags & cpu_mask &&
		    clkr->flags & DEFAULT_RATE)
			break; /* Found the default rate for this platform */
	}

so we find an entry which is supported _and_ is the default for the SoC.

There's also a second issue - the comments before omap2_divisor_to_clksel()
indicate that this function returns 0xffffffff on error.  Unfortunately,
this is not so, it actually returns zero on error.  Moreover, we test
the result of the function against ~0, so we'll never deal with the error
case.  This really should be fixed so that we return the right value for
the error case.  (Further comments on this in a follow up.)

So, below is a patch which fixes both of these issues.

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 5020cb1..f87501b 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -636,7 +636,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
  *
  * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
  * find the corresponding register field value.  The return register value is
- * the value before left-shifting.  Returns 0xffffffff on error
+ * the value before left-shifting.  Returns ~0 on error
  */
 u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 {
@@ -648,7 +648,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
 	if (!clks)
-		return 0;
+		return ~0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
 		if ((clkr->flags & cpu_mask) && (clkr->div == div))
@@ -659,7 +659,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 		printk(KERN_ERR "clock: Could not find divisor %d for "
 		       "clock %s parent %s\n", div, clk->name,
 		       clk->parent->name);
-		return 0;
+		return ~0;
 	}
 
 	return clkr->val;
@@ -747,7 +747,7 @@ static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
 		return 0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
-		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
+		if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
 			break; /* Found the default rate for this platform */
 	}
 

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-14 11:23           ` Russell King - ARM Linux
@ 2009-02-14 11:36             ` Russell King - ARM Linux
  2009-02-25  9:45               ` Paul Walmsley
  2009-02-19 12:19             ` Russell King - ARM Linux
  2009-02-22 23:37             ` Paul Walmsley
  2 siblings, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-14 11:36 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

On Sat, Feb 14, 2009 at 11:23:25AM +0000, Russell King - ARM Linux wrote:
> There's also a second issue - the comments before omap2_divisor_to_clksel()
> indicate that this function returns 0xffffffff on error.  Unfortunately,
> this is not so, it actually returns zero on error.  Moreover, we test
> the result of the function against ~0, so we'll never deal with the error
> case.  This really should be fixed so that we return the right value for
> the error case.  (Further comments on this in a follow up.)

The thing I don't like about this is that we have several functions looking
up clksel_rate entries, some of which return 0 on error and others ~0 on
error.

This is very prone to mistakes - and is probably why the original problem
has occurred.  I'd much prefer to fix the underlying confusion rather
than letting it persist, by making all these lookup functions return the
clksel_rate pointer or NULL.

Not only does that avoid the question about whether the function returns
0 or ~0 on error, but it also gets rid of the horrible return-through-pointer
style of _omap2_clksel_get_src_field() which itself is error prone.
(The kernel has had a few cases where this kind of thing has lead to
uninitialized use, so avoiding this where it's easy to do so makes
sense.)

One final point:

        if (parent_div > 0)
                clk->rate /= parent_div;

seems to be impossible to be false - the old code used div == 0 in the
tables as the end of table sentinel, and if it is encountered, 
_omap2_clksel_get_src_field (and the newer omap2_clksel_lookup_parent)
causes failure to occur.  Also, since parent_div is unsigned, the only
case where the above statement is false is when div == 0.  So, the code
can be further simplified to:

 	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
 	clk->rate = new_parent->rate / clkr->div;

Agreed?

diff -u a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -596,23 +596,24 @@
 }
 
 /**
- * omap2_clksel_to_divisor() - turn clksel field value into integer divider
+ * omap2_clksel_lookup_field() - lookup clksel_rate for clksel field value
  * @clk: OMAP struct clk to use
  * @field_val: register field value to find
  *
  * Given a struct clk of a rate-selectable clksel clock, and a register field
- * value to search for, find the corresponding clock divisor.  The register
+ * value to search for, find the corresponding clksel_rate entry.  The register
  * field value should be pre-masked and shifted down so the LSB is at bit 0
- * before calling.  Returns 0 on error
+ * before calling.  Returns NULL on error.
  */
-u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
+static const
+struct clksel_rate *omap2_clksel_lookup_field(struct clk *clk, u32 field_val)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
 	if (!clks)
-		return 0;
+		return NULL;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
 		if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
@@ -623,22 +624,22 @@
 		printk(KERN_ERR "clock: Could not find fieldval %d for "
 		       "clock %s parent %s\n", field_val, clk->name,
 		       clk->parent->name);
-		return 0;
+		return NULL;
 	}
 
-	return clkr->div;
+	return clkr;
 }
 
 /**
- * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
+ * omap2_clksel_lookup_divisor() - lookup clksel_rate for integer divisor
  * @clk: OMAP struct clk to use
  * @div: integer divisor to search for
  *
- * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
- * find the corresponding register field value.  The return register value is
- * the value before left-shifting.  Returns ~0 on error
+ * Given a struct clk of a rate-selectable clksel clock and a clock divisor,
+ * find the corresponding clksel_rate entry.  Returns NULL on error.
  */
-u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
+static const
+struct clksel_rate *omap2_clksel_lookup_divisor(struct clk *clk, u32 div)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
@@ -648,7 +649,7 @@
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
 	if (!clks)
-		return ~0;
+		return NULL;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
 		if ((clkr->flags & cpu_mask) && (clkr->div == div))
@@ -659,10 +660,10 @@
 		printk(KERN_ERR "clock: Could not find divisor %d for "
 		       "clock %s parent %s\n", div, clk->name,
 		       clk->parent->name);
-		return ~0;
+		return NULL;
 	}
 
-	return clkr->val;
+	return clkr;
 }
 
 /**
@@ -673,6 +674,7 @@
  */
 u32 omap2_clksel_get_divisor(struct clk *clk)
 {
+	const struct clksel_rate *clkr;
 	u32 v;
 
 	if (!clk->clksel_mask)
@@ -681,11 +683,14 @@
 	v = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
 	v >>= __ffs(clk->clksel_mask);
 
-	return omap2_clksel_to_divisor(clk, v);
+	clkr = omap2_clksel_lookup_field(clk, v);
+
+	return clkr ? clkr->val : 0;
 }
 
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 {
+	const struct clksel_rate *clkr;
 	u32 v, field_val, validrate, new_div = 0;
 
 	if (!clk->clksel_mask)
@@ -695,17 +700,17 @@
 	if (validrate != rate)
 		return -EINVAL;
 
-	field_val = omap2_divisor_to_clksel(clk, new_div);
-	if (field_val == ~0)
+	clkr = omap2_clksel_lookup_divisor(clk, new_div);
+	if (!clkr)
 		return -EINVAL;
 
 	v = __raw_readl(clk->clksel_reg);
 	v &= ~clk->clksel_mask;
-	v |= field_val << __ffs(clk->clksel_mask);
+	v |= clkr->val << __ffs(clk->clksel_mask);
 	__raw_writel(v, clk->clksel_reg);
 	v = __raw_readl(clk->clksel_reg); /* OCP barrier */
 
-	clk->rate = clk->parent->rate / new_div;
+	clk->rate = clk->parent->rate / clkr->div;
 
 	_omap2xxx_clk_commit(clk);
 
@@ -733,18 +738,18 @@
 }
 
 /*
- * Converts encoded control register address into a full address
- * On error, the return value (parent_div) will be 0.
+ * Given a struct clk of a rate-selectable clksel clock and a parent clock,
+ * find the default clksel_rate entry.  Returns NULL on error.
  */
-static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
-				       u32 *field_val)
+static const
+struct clksel_rate *omap2_clksel_lookup_parent(struct clk *clk, struct clk *parent)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 
-	clks = omap2_get_clksel_by_parent(clk, src_clk);
+	clks = omap2_get_clksel_by_parent(clk, parent);
 	if (!clks)
-		return 0;
+		return NULL;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
 		if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
@@ -755,20 +760,19 @@
 		printk(KERN_ERR "clock: Could not find default rate for "
 		       "clock %s parent %s\n", clk->name,
 		       src_clk->parent->name);
-		return 0;
+		return NULL;
 	}
 
 	/* Should never happen.  Add a clksel mask to the struct clk. */
 	WARN_ON(clk->clksel_mask == 0);
 
-	*field_val = clkr->val;
-
-	return clkr->div;
+	return NULL;
 }
 
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 {
-	u32 field_val, v, parent_div;
+	const struct clksel_rate *clkr;
+	u32 v;
 
 	if (clk->flags & CONFIG_PARTICIPANT)
 		return -EINVAL;
@@ -776,8 +780,8 @@
 	if (!clk->clksel)
 		return -EINVAL;
 
-	parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val);
-	if (!parent_div)
+	clkr = omap2_clksel_lookup_parent(clk, new_parent);
+	if (!clkr)
 		return -EINVAL;
 
 	if (clk->usecount > 0)
@@ -786,7 +790,7 @@
 	/* Set new source value (previous dividers if any in effect) */
 	v = __raw_readl(clk->clksel_reg);
 	v &= ~clk->clksel_mask;
-	v |= field_val << __ffs(clk->clksel_mask);
+	v |= clkr->val << __ffs(clk->clksel_mask);
 	__raw_writel(v, clk->clksel_reg);
 	v = __raw_readl(clk->clksel_reg);    /* OCP barrier */
 
@@ -800,8 +804,8 @@
 	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
 	clk->rate = new_parent->rate;
 
-	if (parent_div > 0)
-		clk->rate /= parent_div;
+	if (clkr->div > 0)
+		clk->rate /= clkr->div;
 
 	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
 		 clk->name, clk->parent->name, clk->rate);
diff -u a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -42,8 +42,6 @@ void omap2_init_clksel_parent(struct clk *clk);
 u32 omap2_clksel_get_divisor(struct clk *clk);
 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);
 unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-14 11:23           ` Russell King - ARM Linux
  2009-02-14 11:36             ` Russell King - ARM Linux
@ 2009-02-19 12:19             ` Russell King - ARM Linux
  2009-02-20  0:50               ` Woodruff, Richard
  2009-02-22 23:37             ` Paul Walmsley
  2 siblings, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-19 12:19 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

On Sat, Feb 14, 2009 at 11:23:25AM +0000, Russell King - ARM Linux wrote:
> On Fri, Feb 13, 2009 at 12:01:37AM -0700, Paul Walmsley wrote:
> > (cc'ing Richard Woodruff)
> > 
> > Hello Russell,
> > 
> > On Mon, 9 Feb 2009, Russell King - ARM Linux wrote:
> > 
> > > On Thu, Jan 29, 2009 at 10:06:08PM +0000, Russell King - ARM Linux wrote:
> > > > @@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
> > > >  	if (clk->usecount > 0)
> > > >  		_omap2_clk_enable(clk);
> > > >  
> > > > -	clk->parent = new_parent;
> > > > +	clk_reparent(clk, new_parent);
> > > 
> > > While looking at the DPLL patches, I've realised that omap2_clk_set_parent()
> > > is buggy, as are any other places which reparent the clock (thankfully
> > > the only other place is in the initialisation code where it doesn't
> > > matter.)
> > > 
> > > Consider what happens when a clock is enabled - we walk up the tree
> > > enabling all parents.  If we then change the clock's parent, and
> > > then disable the child, we will again walk up the tree, but since
> > > we've reparented it, it will be a different clock tree.  The result
> > > is that the ancestors clock usage counts, and therefore their enable
> > > status, will end up getting screwed up.
> > 
> > Agreed.
> > 
> > > This brings up a question: what we currently do here is:
> > > 
> > > - disable the child
> > > - program clksel
> > > - enable the child
> > > - change child->parent
> > > 
> > > If we add in the parent handling, there are two possibilities:
> > > 
> > > - disable the child
> > > - enable the new parent tree
> > > - program clksel
> > > - change child->parent
> > > - disable the old parent tree
> > > - enable the child
> > > 
> > > OR
> > > 
> > > - disable the child and the old parent tree
> > > - program clksel
> > > - change child->parent
> > > - enable the new parent tree and the child
> > > 
> > > (note those 'and's have implied ordering).
> > > 
> > > Is there anything which dictates one approach over the other?
> > > Obviously the latter approach results in something smaller and
> > > cleaner, but might not be technically correct.
> > 
> > I don't know of any hardware reason to prefer one approach over the other, 
> > but Richard might know better.
> 
> I'll need an answer on this before I can commit the updated bypass clock
> support patch.

In the interests of moving things forward, and due to the total lack of
response from TI, it's time to make a decision based upon what seems
sensible so things can continue moving forward.

Since there are no hardware issues we know about, we might as well take
the simplest approach, which is the latter case.

> However, looking a little deeper, there's more issues in the reparenting
> area.  I don't think this code has been tested at all...  In
> _omap2_clksel_get_src_field, there is this:
> 
> 	for (clkr = clks->rates; clkr->div; clkr++) {
> 		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
> 			break; /* Found the default rate for this platform */
> 	}
> 
> which is bogus - it will find the first entry which is _either_ marked
> as a default rate _or_ is supported by the SoC.  This means (for
> instance) that:
> 
> static const struct clksel_rate core_l3_core_rates[] = {
>         { .div = 1, .val = 1, .flags = RATE_IN_24XX },
>         { .div = 2, .val = 2, .flags = RATE_IN_242X },
>         { .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },
> 
> will give us divisor 1 rather than presumably the one we want, that being
> divisor 4.  I think the test above should be:
> 
> 	for (clkr = clks->rates; clkr->div; clkr++) {
> 		if (clkr->flags & cpu_mask &&
> 		    clkr->flags & DEFAULT_RATE)
> 			break; /* Found the default rate for this platform */
> 	}
> 
> so we find an entry which is supported _and_ is the default for the SoC.
> 
> There's also a second issue - the comments before omap2_divisor_to_clksel()
> indicate that this function returns 0xffffffff on error.  Unfortunately,
> this is not so, it actually returns zero on error.  Moreover, we test
> the result of the function against ~0, so we'll never deal with the error
> case.  This really should be fixed so that we return the right value for
> the error case.  (Further comments on this in a follow up.)
> 
> So, below is a patch which fixes both of these issues.

No comments received, I'm going to assume everyone is happy with the
patch below and it will be going to Linus today or this evening.

> diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
> index 5020cb1..f87501b 100644
> --- a/arch/arm/mach-omap2/clock.c
> +++ b/arch/arm/mach-omap2/clock.c
> @@ -636,7 +636,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
>   *
>   * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
>   * find the corresponding register field value.  The return register value is
> - * the value before left-shifting.  Returns 0xffffffff on error
> + * the value before left-shifting.  Returns ~0 on error
>   */
>  u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
>  {
> @@ -648,7 +648,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
>  
>  	clks = omap2_get_clksel_by_parent(clk, clk->parent);
>  	if (!clks)
> -		return 0;
> +		return ~0;
>  
>  	for (clkr = clks->rates; clkr->div; clkr++) {
>  		if ((clkr->flags & cpu_mask) && (clkr->div == div))
> @@ -659,7 +659,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
>  		printk(KERN_ERR "clock: Could not find divisor %d for "
>  		       "clock %s parent %s\n", div, clk->name,
>  		       clk->parent->name);
> -		return 0;
> +		return ~0;
>  	}
>  
>  	return clkr->val;
> @@ -747,7 +747,7 @@ static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
>  		return 0;
>  
>  	for (clkr = clks->rates; clkr->div; clkr++) {
> -		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
> +		if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
>  			break; /* Found the default rate for this platform */
>  	}
>  
> 
> -------------------------------------------------------------------
> List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
> FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
> Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php

^ permalink raw reply	[flat|nested] 50+ messages in thread

* RE: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-19 12:19             ` Russell King - ARM Linux
@ 2009-02-20  0:50               ` Woodruff, Richard
  2009-02-23 16:03                 ` Russell King - ARM Linux
  0 siblings, 1 reply; 50+ messages in thread
From: Woodruff, Richard @ 2009-02-20  0:50 UTC (permalink / raw)
  To: Russell King - ARM Linux, Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren


> From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> Sent: Thursday, February 19, 2009 6:20 AM

> > > > Consider what happens when a clock is enabled - we walk up the tree
> > > > enabling all parents.  If we then change the clock's parent, and
> > > > then disable the child, we will again walk up the tree, but since
> > > > we've reparented it, it will be a different clock tree.  The result
> > > > is that the ancestors clock usage counts, and therefore their enable
> > > > status, will end up getting screwed up.
> > >
> > > Agreed.

The historic usage of this has been against single use leaf clocks (1st instance of gptimer).  When it was used it did:
        clk_get()
        clk_set_parent()
        clk_enable()

This usage was ok for that. Use on a disabled clock is needed.

If there are multiple users on the clock or it is enabled there are problems.

> > > > This brings up a question: what we currently do here is:
> > > >
> > > > - disable the child
> > > > - program clksel
> > > > - enable the child
> > > > - change child->parent
> > > >
> > > > If we add in the parent handling, there are two possibilities:
> > > >
> > > > - disable the child
> > > > - enable the new parent tree
> > > > - program clksel
> > > > - change child->parent
> > > > - disable the old parent tree
> > > > - enable the child
> > > >
> > > > OR
> > > >
> > > > - disable the child and the old parent tree
> > > > - program clksel
> > > > - change child->parent
> > > > - enable the new parent tree and the child
> > > >
> > > > (note those 'and's have implied ordering).
> > > >
> > > > Is there anything which dictates one approach over the other?
> > > > Obviously the latter approach results in something smaller and
> > > > cleaner, but might not be technically correct.
> > >
> > > I don't know of any hardware reason to prefer one approach over the other,
> > > but Richard might know better.

I'm not aware of any hw issue. I like option #2 it keeps parent tree (likely) off when divider is set.

The call can still be unfriendly if 2 different drivers are using the clock with their own clock get/enable. It might be the function should return an error if usecount != 0 to stop surprises.  It is all around better if the parenting is done when the clock is off.

The end user needs to be smart also. If the module has local divider it should set it _before_ enabling the clock. Letting a clock which is too fast for you propagate in can cause badness.

clk_get
clk_set_parent
rate = Clk_get_rate
set local divider
clk_enable

Regards,
Richard W.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-14 11:23           ` Russell King - ARM Linux
  2009-02-14 11:36             ` Russell King - ARM Linux
  2009-02-19 12:19             ` Russell King - ARM Linux
@ 2009-02-22 23:37             ` Paul Walmsley
  2009-02-24  9:43               ` Russell King - ARM Linux
  2 siblings, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-02-22 23:37 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

Hello Russell,

On Sat, 14 Feb 2009, Russell King - ARM Linux wrote:

> However, looking a little deeper, there's more issues in the reparenting
> area.  I don't think this code has been tested at all...  In
> _omap2_clksel_get_src_field, there is this:
> 
> 	for (clkr = clks->rates; clkr->div; clkr++) {
> 		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
> 			break; /* Found the default rate for this platform */
> 	}
> 
> which is bogus - it will find the first entry which is _either_ marked
> as a default rate _or_ is supported by the SoC.  This means (for
> instance) that:
> 
> static const struct clksel_rate core_l3_core_rates[] = {
>         { .div = 1, .val = 1, .flags = RATE_IN_24XX },
>         { .div = 2, .val = 2, .flags = RATE_IN_242X },
>         { .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },
> 
> will give us divisor 1 rather than presumably the one we want, that being
> divisor 4.  I think the test above should be:
> 
> 	for (clkr = clks->rates; clkr->div; clkr++) {
> 		if (clkr->flags & cpu_mask &&
> 		    clkr->flags & DEFAULT_RATE)
> 			break; /* Found the default rate for this platform */
> 	}
> 
> so we find an entry which is supported _and_ is the default for the SoC.

Agreed.

> There's also a second issue - the comments before omap2_divisor_to_clksel()
> indicate that this function returns 0xffffffff on error.  Unfortunately,
> this is not so, it actually returns zero on error.  Moreover, we test
> the result of the function against ~0, so we'll never deal with the error
> case.  This really should be fixed so that we return the right value for
> the error case.  (Further comments on this in a follow up.)

Agreed here also.

> So, below is a patch which fixes both of these issues.

Looks good, thanks Russell.

Acked-by: Paul Walmsley <paul@pwsan.com>


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta
  2009-01-28 19:28 ` [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta Paul Walmsley
@ 2009-02-23 15:50   ` Russell King - ARM Linux
  2009-03-02 22:35     ` Paul Walmsley
  0 siblings, 1 reply; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-23 15:50 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Wed, Jan 28, 2009 at 12:28:01PM -0700, Paul Walmsley wrote:
> 4. 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.

Hmm.  Completely agree over the naming issue, however I think this
opens a hole.

> @@ -780,12 +772,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)
>  		ret = clk->set_rate(clk, rate);
>  

The removal of this can be mitigated as indicated; not having a set_rate
method does indeed cause this to return -EINVAL.

> @@ -830,9 +816,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;
>  

This one, however, is not...

> @@ -1020,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 | RATE_PROPAGATES,
> +				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
>  };
>  
>  /*

For example, here we have a clock which was previously marked with
CONFIG_PARTICIPANT, and has a non-NULL clksel member.  This means
that clk_set_parent() would return -EINVAL before, but would have
an effect after the removal of this flag.

The same is true of dsp_fck, dsp_irate_ick, iva1_ifck, core_l3_ck,
usb_l4_ick and mdm_ick.

So, is this change safe for these clocks?

(Note: all the other flags have already gone in my tree.)

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-20  0:50               ` Woodruff, Richard
@ 2009-02-23 16:03                 ` Russell King - ARM Linux
  2009-02-24 12:35                   ` Woodruff, Richard
  2009-03-02 23:02                   ` Paul Walmsley
  0 siblings, 2 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-23 16:03 UTC (permalink / raw)
  To: Woodruff, Richard
  Cc: Paul Walmsley, linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

On Thu, Feb 19, 2009 at 06:50:52PM -0600, Woodruff, Richard wrote:
> The historic usage of this has been against single use leaf clocks (1st instance of gptimer).  When it was used it did:
>         clk_get()
>         clk_set_parent()
>         clk_enable()
> 
> This usage was ok for that. Use on a disabled clock is needed.
> 
> If there are multiple users on the clock or it is enabled there are problems.

It sounds to me like clk_set_parent() needs this then to prevent enabled
clocks being reparented.  By doing so, we no longer need to disable/enable
the clock within the OMAP2/3 set_parent function since we are now
guaranteed that the clock will be disabled.

Ack?

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 40cb65b..f49bce9 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -807,9 +807,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	if (!parent_div)
 		return -EINVAL;
 
-	if (clk->usecount > 0)
-		_omap2_clk_disable(clk);
-
 	/* Set new source value (previous dividers if any in effect) */
 	v = __raw_readl(clk->clksel_reg);
 	v &= ~clk->clksel_mask;
@@ -819,9 +816,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 
 	_omap2xxx_clk_commit(clk);
 
-	if (clk->usecount > 0)
-		_omap2_clk_enable(clk);
-
 	clk_reparent(clk, new_parent);
 
 	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 08baa18..b2d9e1f 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -144,12 +144,14 @@ 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 (ret == 0) {
-		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
-		propagate_rate(clk);
+	if (clk->usecount == 0) {
+		if (arch_clock->clk_set_parent)
+			ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0) {
+			if (clk->recalc)
+				clk->rate = clk->recalc(clk);
+			propagate_rate(clk);
+		}
 	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-22 23:37             ` Paul Walmsley
@ 2009-02-24  9:43               ` Russell King - ARM Linux
  0 siblings, 0 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-02-24  9:43 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

On Sun, Feb 22, 2009 at 04:37:31PM -0700, Paul Walmsley wrote:
> Hello Russell,
> 
> On Sat, 14 Feb 2009, Russell King - ARM Linux wrote:
> > However, looking a little deeper, there's more issues in the reparenting
> > area.  I don't think this code has been tested at all...  In
> > _omap2_clksel_get_src_field, there is this:
> > 
> > 	for (clkr = clks->rates; clkr->div; clkr++) {
> > 		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
> > 			break; /* Found the default rate for this platform */
> > 	}
> > 
> > which is bogus - it will find the first entry which is _either_ marked
> > as a default rate _or_ is supported by the SoC.  This means (for
> > instance) that:
> > 
> > static const struct clksel_rate core_l3_core_rates[] = {
> >         { .div = 1, .val = 1, .flags = RATE_IN_24XX },
> >         { .div = 2, .val = 2, .flags = RATE_IN_242X },
> >         { .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },
> > 
> > will give us divisor 1 rather than presumably the one we want, that being
> > divisor 4.  I think the test above should be:
> > 
> > 	for (clkr = clks->rates; clkr->div; clkr++) {
> > 		if (clkr->flags & cpu_mask &&
> > 		    clkr->flags & DEFAULT_RATE)
> > 			break; /* Found the default rate for this platform */
> > 	}
> > 
> > so we find an entry which is supported _and_ is the default for the SoC.
> 
> Agreed.
> 
> > There's also a second issue - the comments before omap2_divisor_to_clksel()
> > indicate that this function returns 0xffffffff on error.  Unfortunately,
> > this is not so, it actually returns zero on error.  Moreover, we test
> > the result of the function against ~0, so we'll never deal with the error
> > case.  This really should be fixed so that we return the right value for
> > the error case.  (Further comments on this in a follow up.)
> 
> Agreed here also.
> 
> > So, below is a patch which fixes both of these issues.
> 
> Looks good, thanks Russell.
> 
> Acked-by: Paul Walmsley <paul@pwsan.com>

You're too late; it went to Linus last Thursday and is in -rc6.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* RE: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-23 16:03                 ` Russell King - ARM Linux
@ 2009-02-24 12:35                   ` Woodruff, Richard
  2009-03-02 23:02                   ` Paul Walmsley
  1 sibling, 0 replies; 50+ messages in thread
From: Woodruff, Richard @ 2009-02-24 12:35 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Paul Walmsley, linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren


> From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> Sent: Monday, February 23, 2009 10:04 AM
> To: Woodruff, Richard

> Ack?

Ack.

> diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
> index 08baa18..b2d9e1f 100644
> --- a/arch/arm/plat-omap/clock.c
> +++ b/arch/arm/plat-omap/clock.c
> @@ -144,12 +144,14 @@ 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 (ret == 0) {
> -             if (clk->recalc)
> -                     clk->rate = clk->recalc(clk);
> -             propagate_rate(clk);
> +     if (clk->usecount == 0) {
> +             if (arch_clock->clk_set_parent)
> +                     ret = arch_clock->clk_set_parent(clk, parent);
> +             if (ret == 0) {
> +                     if (clk->recalc)
> +                             clk->rate = clk->recalc(clk);
> +                     propagate_rate(clk);
> +             }
>       }
>       spin_unlock_irqrestore(&clockfw_lock, flags);
>


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-14 11:36             ` Russell King - ARM Linux
@ 2009-02-25  9:45               ` Paul Walmsley
  0 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-02-25  9:45 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, r-woodruff2, Tony Lindgren

Hello Russell,

On Sat, 14 Feb 2009, Russell King - ARM Linux wrote:

> On Sat, Feb 14, 2009 at 11:23:25AM +0000, Russell King - ARM Linux wrote:
> > There's also a second issue - the comments before omap2_divisor_to_clksel()
> > indicate that this function returns 0xffffffff on error.  Unfortunately,
> > this is not so, it actually returns zero on error.  Moreover, we test
> > the result of the function against ~0, so we'll never deal with the error
> > case.  This really should be fixed so that we return the right value for
> > the error case.  (Further comments on this in a follow up.)
> 
> The thing I don't like about this is that we have several functions looking
> up clksel_rate entries, some of which return 0 on error and others ~0 on
> error.
> 
> This is very prone to mistakes - and is probably why the original problem
> has occurred.  I'd much prefer to fix the underlying confusion rather
> than letting it persist, by making all these lookup functions return the
> clksel_rate pointer or NULL.
> 
> Not only does that avoid the question about whether the function returns
> 0 or ~0 on error, but it also gets rid of the horrible return-through-pointer
> style of _omap2_clksel_get_src_field() which itself is error prone.
> (The kernel has had a few cases where this kind of thing has lead to
> uninitialized use, so avoiding this where it's easy to do so makes
> sense.)
> 
> One final point:
> 
>         if (parent_div > 0)
>                 clk->rate /= parent_div;
> 
> seems to be impossible to be false - the old code used div == 0 in the
> tables as the end of table sentinel, and if it is encountered, 
> _omap2_clksel_get_src_field (and the newer omap2_clksel_lookup_parent)
> causes failure to occur.  Also, since parent_div is unsigned, the only
> case where the above statement is false is when div == 0.  So, the code
> can be further simplified to:
> 
>  	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
>  	clk->rate = new_parent->rate / clkr->div;
> 
> Agreed?

Agreed on both points -- a few comments on the patch:

> diff -u a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
> --- a/arch/arm/mach-omap2/clock.c
> +++ b/arch/arm/mach-omap2/clock.c
> @@ -596,23 +596,24 @@
>  }
>  
>  /**
> - * omap2_clksel_to_divisor() - turn clksel field value into integer divider
> + * omap2_clksel_lookup_field() - lookup clksel_rate for clksel field value
>   * @clk: OMAP struct clk to use
>   * @field_val: register field value to find
>   *
>   * Given a struct clk of a rate-selectable clksel clock, and a register field
> - * value to search for, find the corresponding clock divisor.  The register
> + * value to search for, find the corresponding clksel_rate entry.  The register
>   * field value should be pre-masked and shifted down so the LSB is at bit 0
> - * before calling.  Returns 0 on error
> + * before calling.  Returns NULL on error.
>   */
> -u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
> +static const
> +struct clksel_rate *omap2_clksel_lookup_field(struct clk *clk, u32 field_val)
>  {
>  	const struct clksel *clks;
>  	const struct clksel_rate *clkr;
>  
>  	clks = omap2_get_clksel_by_parent(clk, clk->parent);
>  	if (!clks)
> -		return 0;
> +		return NULL;
>  
>  	for (clkr = clks->rates; clkr->div; clkr++) {
>  		if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
> @@ -623,22 +624,22 @@
>  		printk(KERN_ERR "clock: Could not find fieldval %d for "
>  		       "clock %s parent %s\n", field_val, clk->name,
>  		       clk->parent->name);
> -		return 0;
> +		return NULL;
>  	}
>  
> -	return clkr->div;
> +	return clkr;
>  }
>  
>  /**
> - * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
> + * omap2_clksel_lookup_divisor() - lookup clksel_rate for integer divisor
>   * @clk: OMAP struct clk to use
>   * @div: integer divisor to search for
>   *
> - * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
> - * find the corresponding register field value.  The return register value is
> - * the value before left-shifting.  Returns ~0 on error
> + * Given a struct clk of a rate-selectable clksel clock and a clock divisor,
> + * find the corresponding clksel_rate entry.  Returns NULL on error.
>   */
> -u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
> +static const
> +struct clksel_rate *omap2_clksel_lookup_divisor(struct clk *clk, u32 div)
>  {
>  	const struct clksel *clks;
>  	const struct clksel_rate *clkr;
> @@ -648,7 +649,7 @@
>  
>  	clks = omap2_get_clksel_by_parent(clk, clk->parent);
>  	if (!clks)
> -		return ~0;
> +		return NULL;
>  
>  	for (clkr = clks->rates; clkr->div; clkr++) {
>  		if ((clkr->flags & cpu_mask) && (clkr->div == div))
> @@ -659,10 +660,10 @@
>  		printk(KERN_ERR "clock: Could not find divisor %d for "
>  		       "clock %s parent %s\n", div, clk->name,
>  		       clk->parent->name);
> -		return ~0;
> +		return NULL;
>  	}
>  
> -	return clkr->val;
> +	return clkr;
>  }
>  
>  /**
> @@ -673,6 +674,7 @@
>   */
>  u32 omap2_clksel_get_divisor(struct clk *clk)
>  {
> +	const struct clksel_rate *clkr;
>  	u32 v;
>  
>  	if (!clk->clksel_mask)
> @@ -681,11 +683,14 @@
>  	v = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
>  	v >>= __ffs(clk->clksel_mask);
>  
> -	return omap2_clksel_to_divisor(clk, v);
> +	clkr = omap2_clksel_lookup_field(clk, v);
> +
> +	return clkr ? clkr->val : 0;
>  }
>  
>  int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
>  {
> +	const struct clksel_rate *clkr;
>  	u32 v, field_val, validrate, new_div = 0;
>  
>  	if (!clk->clksel_mask)
> @@ -695,17 +700,17 @@
>  	if (validrate != rate)
>  		return -EINVAL;
>  
> -	field_val = omap2_divisor_to_clksel(clk, new_div);
> -	if (field_val == ~0)
> +	clkr = omap2_clksel_lookup_divisor(clk, new_div);
> +	if (!clkr)
>  		return -EINVAL;
>  
>  	v = __raw_readl(clk->clksel_reg);
>  	v &= ~clk->clksel_mask;
> -	v |= field_val << __ffs(clk->clksel_mask);
> +	v |= clkr->val << __ffs(clk->clksel_mask);
>  	__raw_writel(v, clk->clksel_reg);
>  	v = __raw_readl(clk->clksel_reg); /* OCP barrier */
>  
> -	clk->rate = clk->parent->rate / new_div;
> +	clk->rate = clk->parent->rate / clkr->div;
>  
>  	_omap2xxx_clk_commit(clk);
>  
> @@ -733,18 +738,18 @@
>  }
>  
>  /*
> - * Converts encoded control register address into a full address
> - * On error, the return value (parent_div) will be 0.
> + * Given a struct clk of a rate-selectable clksel clock and a parent clock,
> + * find the default clksel_rate entry.  Returns NULL on error.
>   */
> -static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
> -				       u32 *field_val)
> +static const
> +struct clksel_rate *omap2_clksel_lookup_parent(struct clk *clk, struct clk *parent)
>  {
>  	const struct clksel *clks;
>  	const struct clksel_rate *clkr;
>  
> -	clks = omap2_get_clksel_by_parent(clk, src_clk);
> +	clks = omap2_get_clksel_by_parent(clk, parent);
>  	if (!clks)
> -		return 0;
> +		return NULL;
>  
>  	for (clkr = clks->rates; clkr->div; clkr++) {
>  		if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
> @@ -755,20 +760,19 @@
>  		printk(KERN_ERR "clock: Could not find default rate for "
>  		       "clock %s parent %s\n", clk->name,
>  		       src_clk->parent->name);
> -		return 0;
> +		return NULL;
>  	}
>  
>  	/* Should never happen.  Add a clksel mask to the struct clk. */
>  	WARN_ON(clk->clksel_mask == 0);
>  
> -	*field_val = clkr->val;
> -
> -	return clkr->div;
> +	return NULL;

This should return clkr.

>  }
>  
>  int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
>  {
> -	u32 field_val, v, parent_div;
> +	const struct clksel_rate *clkr;
> +	u32 v;
>  
>  	if (clk->flags & CONFIG_PARTICIPANT)
>  		return -EINVAL;
> @@ -776,8 +780,8 @@
>  	if (!clk->clksel)
>  		return -EINVAL;
>  
> -	parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val);
> -	if (!parent_div)
> +	clkr = omap2_clksel_lookup_parent(clk, new_parent);
> +	if (!clkr)
>  		return -EINVAL;
>  
>  	if (clk->usecount > 0)
> @@ -786,7 +790,7 @@
>  	/* Set new source value (previous dividers if any in effect) */
>  	v = __raw_readl(clk->clksel_reg);
>  	v &= ~clk->clksel_mask;
> -	v |= field_val << __ffs(clk->clksel_mask);
> +	v |= clkr->val << __ffs(clk->clksel_mask);
>  	__raw_writel(v, clk->clksel_reg);
>  	v = __raw_readl(clk->clksel_reg);    /* OCP barrier */
>  
> @@ -800,8 +804,8 @@
>  	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
>  	clk->rate = new_parent->rate;
>  
> -	if (parent_div > 0)
> -		clk->rate /= parent_div;
> +	if (clkr->div > 0)
> +		clk->rate /= clkr->div;

The conditional can be removed, per your second point above.

>  
>  	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
>  		 clk->name, clk->parent->name, clk->rate);
> diff -u a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
> --- a/arch/arm/mach-omap2/clock.h
> +++ b/arch/arm/mach-omap2/clock.h
> @@ -42,8 +42,6 @@ void omap2_init_clksel_parent(struct clk *clk);
>  u32 omap2_clksel_get_divisor(struct clk *clk);
>  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);
>  unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
>  long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
>  int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
> 


- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta
  2009-02-23 15:50   ` Russell King - ARM Linux
@ 2009-03-02 22:35     ` Paul Walmsley
  0 siblings, 0 replies; 50+ messages in thread
From: Paul Walmsley @ 2009-03-02 22:35 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Tony Lindgren

Hi Russell,

On Mon, 23 Feb 2009, Russell King - ARM Linux wrote:

> On Wed, Jan 28, 2009 at 12:28:01PM -0700, Paul Walmsley wrote:
> > 4. 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.
> 
> Hmm.  Completely agree over the naming issue, however I think this
> opens a hole.

[...]

> > @@ -1020,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 | RATE_PROPAGATES,
> > +				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
> >  };
> 
> For example, here we have a clock which was previously marked with
> CONFIG_PARTICIPANT, and has a non-NULL clksel member.  This means
> that clk_set_parent() would return -EINVAL before, but would have
> an effect after the removal of this flag.
> 
> The same is true of dsp_fck, dsp_irate_ick, iva1_ifck, core_l3_ck,
> usb_l4_ick and mdm_ick.
> 
> So, is this change safe for these clocks?

We should probably block clk_set_parent() on those clocks also, even 
though they only support one parent.  Attached below is an updated version 
of patch E 12 that fixes the problem.  Please let me know if you'd just 
like this fix separately.


- Paul

From: Paul Walmsley <paul@pwsan.com>
Date: Sat, 28 Feb 2009 19:11:23 -0700

OMAP clock: unnecessary clock flag removal fiesta v2

This patch removes four unnecessary clock flags:

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

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

3. Nothing tests the clock flags for VIRTUAL_CLOCK, so it serves no
purpose.  Remove it.

4. 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.  In the unlikely
case that clk_set_parent() is called on a clock with a single parent
clock, simply return 0.  (The previous behavior would reprogram the
clock's rate to the default rate -- this issue was pointed out by
Russell King <linux@arm.linux.org.uk>).


linux-omap source commits are ed950086c69beaabd7179a13b9d2f6c6d0cbddc8,
563aab5521064eae3ece7f3f1f19a32cb5cece4a,
ab0f0e3e3625d5b9abaf37133478c69b4a193521, and
f438e7e9dcd837fd64109256fce82725f7887428.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap1/clock.c             |    3 -
 arch/arm/mach-omap1/clock.h             |   44 +++----
 arch/arm/mach-omap2/clock.c             |   43 ++++---
 arch/arm/mach-omap2/clock24xx.h         |   72 ++++-------
 arch/arm/mach-omap2/clock34xx.h         |  217 +++++++++++-------------------
 arch/arm/plat-omap/include/mach/clock.h |    8 +-
 6 files changed, 156 insertions(+), 231 deletions(-)

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index f3cf6f8..af48050 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -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)
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index df94ad6..5ba55a0 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -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,
@@ -555,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,
@@ -603,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,
@@ -618,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,
@@ -630,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,
@@ -642,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,
@@ -654,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,
@@ -665,7 +663,7 @@ 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,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
 	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
 	.enable_bit	= 6,
 	.enable		= &omap1_clk_enable_generic,
@@ -689,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,
 };
@@ -713,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,
@@ -727,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,
@@ -738,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,
@@ -753,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,
@@ -764,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,
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 6ca67cb..f9acf76 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -194,6 +194,29 @@ void omap2_init_clk_clkdm(struct clk *clk)
 }
 
 /**
+ * _omap_clksel_count_parents - count possible parent clocks of @clk
+ * @clk: OMAP clock struct ptr
+ *
+ * Return the number of possible parents for the clock @clk.  This does not
+ * count the number of possible rates; simply the number of possible
+ * parent clocks.  For example, this function would return
+ * 1 for the OMAP2420 mpu_ck.
+ */
+static u8 _omap_clksel_count_parents(struct clk *clk)
+{
+	const struct clksel *clks;
+	u8 count = 0;
+
+	for (clks = clk->clksel; clks->parent; clks++)
+		count++;
+
+	pr_debug("clock: %s: has %d possible parent clocks\n", clk->name,
+		 count);
+
+	return count;
+}
+
+/**
  * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
  * @clk: OMAP clock struct ptr to use
  *
@@ -561,8 +584,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.
  */
@@ -623,8 +644,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.
  */
@@ -642,10 +661,6 @@ long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
 	if (clk->round_rate)
 		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;
 }
 
@@ -780,12 +795,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)
 		ret = clk->set_rate(clk, rate);
 
@@ -830,9 +839,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;
 
@@ -840,6 +846,9 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 	if (!parent_div)
 		return -EINVAL;
 
+	if (_omap_clksel_count_parents(clk) == 1)
+		return 0;
+
 	if (clk->usecount > 0)
 		_omap2_clk_disable(clk);
 
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index cd9feda..2b7b473 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -628,15 +628,14 @@ static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.rate		= 32000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
 static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
 	.name		= "osc_ck",
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable		= &omap2_enable_osc_ck,
 	.disable	= &omap2_disable_osc_ck,
@@ -648,7 +647,7 @@ static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
 	.name		= "sys_ck",		/* ~ ref_clk also */
 	.parent		= &osc_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_sys_clk_recalc,
 };
@@ -657,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 | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -692,7 +691,7 @@ static struct clk dpll_ck = {
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll_dd,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | ALWAYS_ENABLED,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_dpllcore_recalc,
 	.set_rate	= &omap2_reprogram_dpllcore,
@@ -704,7 +703,7 @@ static struct clk apll96_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 96000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
@@ -718,7 +717,7 @@ static struct clk apll54_ck = {
 	.prcm_mod	= PLL_MOD,
 	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+				ENABLE_ON_INIT,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
@@ -753,7 +752,7 @@ static struct clk func_54m_ck = {
 	.parent		= &apll54_ck,	/* can also be alt_clk */
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -766,7 +765,7 @@ static struct clk core_ck = {
 	.name		= "core_ck",
 	.parent		= &dpll_ck,		/* can also be 32k */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -794,7 +793,7 @@ static struct clk func_96m_ck = {
 	.parent		= &apll96_ck,
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -828,7 +827,7 @@ static struct clk func_48m_ck = {
 	.parent		= &apll96_ck,	 /* 96M or Alt */
 	.prcm_mod	= PLL_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= CM_CLKSEL1,
@@ -844,7 +843,7 @@ static struct clk func_12m_ck = {
 	.parent		= &func_48m_ck,
 	.fixed_div	= 4,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -898,8 +897,7 @@ static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
 	.prcm_mod	= OMAP24XX_GR_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm		= { .name = "prm_clkdm" },
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL_OFFSET,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
@@ -946,7 +944,7 @@ static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
 	.prcm_mod	= OMAP24XX_GR_MOD,
-	.flags		= CLOCK_IN_OMAP242X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm		= { .name = "cm_clkdm" },
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL_OFFSET,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
@@ -1020,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 | RATE_PROPAGATES,
+				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
 };
 
 /*
@@ -1063,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 | RATE_PROPAGATES,
+	.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,
@@ -1072,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 */
@@ -1095,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 */
@@ -1110,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 */
@@ -1121,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,
@@ -1136,8 +1126,7 @@ static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
 	.prcm_mod	= OMAP24XX_DSP_MOD,
-	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
-				RATE_PROPAGATES | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
 	.clkdm		= { .name = "iva1_clkdm" },
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
@@ -1202,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 | RATE_PROPAGATES,
+				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 */
@@ -1231,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,
@@ -1241,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
 };
 
 /*
@@ -1268,7 +1252,7 @@ static struct clk l4_ck = {		/* used both as an ick and fck */
 	.parent		= &core_l3_ck,
 	.prcm_mod	= CORE_MOD,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
+				ALWAYS_ENABLED | DELAYED_APP,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
@@ -1348,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[] = {
@@ -1423,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,
@@ -1431,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 = {
@@ -2848,7 +2830,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 */
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 283c386..179ea17 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -66,16 +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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -83,48 +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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -178,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 | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -205,14 +196,14 @@ static struct clk sys_ck = {
 	.clksel_reg	= OMAP3_PRM_CLKSRC_CTRL_OFFSET,
 	.clksel_mask	= OMAP_SYSCLKDIV_MASK,
 	.clksel		= sys_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk sys_altclk = {
 	.name		= "sys_altclk",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "cm_clkdm" },
 };
 
@@ -223,7 +214,7 @@ static struct clk sys_altclk = {
  */
 static struct clk mcbsp_clks = {
 	.name		= "mcbsp_clks",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 };
 
@@ -294,8 +285,7 @@ static struct clk dpll1_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= MPU_MOD,
 	.dpll_data	= &dpll1_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 	.clkdm		= { .name = "dpll1_clkdm" },
@@ -309,8 +299,7 @@ static struct clk dpll1_ck = {
 static struct clk dpll1_x2_ck = {
 	.name		= "dpll1_x2_ck",
 	.parent		= &dpll1_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll1_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -333,8 +322,7 @@ static struct clk dpll1_x2m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL2_PLL,
 	.clksel_mask	= OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll1_x2m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll1_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -371,8 +359,7 @@ static struct clk dpll2_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= OMAP3430_IVA2_MOD,
 	.dpll_data	= &dpll2_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -398,8 +385,7 @@ static struct clk dpll2_m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL2_PLL,
 	.clksel_mask	= OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll2_m2x2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll2_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -435,8 +421,7 @@ static struct clk dpll3_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll3_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  ALWAYS_ENABLED | RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED | RECALC_ON_ENABLE,
 	.round_rate	= &omap2_dpll_round_rate,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_dpll_recalc,
@@ -449,8 +434,7 @@ static struct clk dpll3_ck = {
 static struct clk dpll3_x2_ck = {
 	.name		= "dpll3_x2_ck",
 	.parent		= &dpll3_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -504,8 +488,7 @@ static struct clk dpll3_m2_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div31_dpll3m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap3_core_dpll_m2_set_rate,
@@ -515,8 +498,7 @@ static struct clk dpll3_m2_ck = {
 static struct clk core_ck = {
 	.name		= "core_ck",
 	.parent		= &dpll3_m2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -524,8 +506,7 @@ static struct clk core_ck = {
 static struct clk dpll3_m2x2_ck = {
 	.name		= "dpll3_m2x2_ck",
 	.parent		= &dpll3_x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -545,8 +526,7 @@ static struct clk dpll3_m3_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_DIV_DPLL3_MASK,
 	.clksel		= div16_dpll3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -558,7 +538,7 @@ static struct clk dpll3_m3x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -566,8 +546,7 @@ static struct clk dpll3_m3x2_ck = {
 static struct clk emu_core_alwon_ck = {
 	.name		= "emu_core_alwon_ck",
 	.parent		= &dpll3_m3x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -602,8 +581,7 @@ static struct clk dpll4_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll4_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -620,8 +598,7 @@ static struct clk dpll4_ck = {
 static struct clk dpll4_x2_ck = {
 	.name		= "dpll4_x2_ck",
 	.parent		= &dpll4_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -640,8 +617,7 @@ static struct clk dpll4_m2_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL3,
 	.clksel_mask	= OMAP3430_DIV_96M_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -653,7 +629,7 @@ static struct clk dpll4_m2x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -667,8 +643,7 @@ static struct clk dpll4_m2x2_ck = {
 static struct clk omap_96m_alwon_fck = {
 	.name		= "omap_96m_alwon_fck",
 	.parent		= &dpll4_m2x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -676,8 +651,7 @@ static struct clk omap_96m_alwon_fck = {
 static struct clk cm_96m_fck = {
 	.name		= "cm_96m_fck",
 	.parent		= &omap_96m_alwon_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -706,8 +680,7 @@ static struct clk omap_96m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_96M_MASK,
 	.clksel		= omap_96m_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -721,8 +694,7 @@ static struct clk dpll4_m3_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_TV_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -735,7 +707,7 @@ static struct clk dpll4_m3x2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -763,8 +735,7 @@ static struct clk omap_54m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_54M_MASK,
 	.clksel		= omap_54m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -792,8 +763,7 @@ static struct clk omap_48m_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_SOURCE_48M_MASK,
 	.clksel		= omap_48m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -802,8 +772,7 @@ static struct clk omap_12m_fck = {
 	.name		= "omap_12m_fck",
 	.parent		= &omap_48m_fck,
 	.fixed_div	= 4,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -817,8 +786,7 @@ static struct clk dpll4_m4_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_DSS1_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -832,7 +800,7 @@ static struct clk dpll4_m4x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_DSS1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -846,8 +814,7 @@ static struct clk dpll4_m5_ck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_CAM_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -859,7 +826,7 @@ static struct clk dpll4_m5x2_ck = {
 	.prcm_mod	= PLL_MOD,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -873,8 +840,7 @@ static struct clk dpll4_m6_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_DIV_DPLL4_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -887,7 +853,7 @@ static struct clk dpll4_m6x2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_CLKEN,
 	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= CLOCK_IN_OMAP343X | INVERT_ENABLE,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -895,8 +861,7 @@ static struct clk dpll4_m6x2_ck = {
 static struct clk emu_per_alwon_ck = {
 	.name		= "emu_per_alwon_ck",
 	.parent		= &dpll4_m6x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -932,8 +897,7 @@ static struct clk dpll5_ck = {
 	.parent		= &sys_ck,
 	.prcm_mod	= PLL_MOD,
 	.dpll_data	= &dpll5_dd,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-			  RECALC_ON_ENABLE,
+	.flags		= CLOCK_IN_OMAP3430ES2 | RECALC_ON_ENABLE,
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -955,8 +919,7 @@ static struct clk dpll5_m2_ck = {
 	.clksel_reg	= OMAP3430ES2_CM_CLKSEL5,
 	.clksel_mask	= OMAP3430ES2_DIV_120M_MASK,
 	.clksel		= div16_dpll5_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP3430ES2 | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "dpll5_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1000,7 +963,7 @@ static struct clk clkout2_src_ck = {
 	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL_OFFSET,
 	.clksel_mask	= OMAP3430_CLKOUT2SOURCE_MASK,
 	.clksel		= clkout2_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1036,8 +999,7 @@ static struct clk sys_clkout2 = {
 static struct clk corex2_fck = {
 	.name		= "corex2_fck",
 	.parent		= &dpll3_m2x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1064,8 +1026,7 @@ static struct clk dpll1_fck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL1_PLL,
 	.clksel_mask	= OMAP3430_MPU_CLK_SRC_MASK,
 	.clksel		= div4_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1073,8 +1034,7 @@ static struct clk dpll1_fck = {
 static struct clk mpu_ck = {
 	.name		= "mpu_ck",
 	.parent		= &dpll1_x2m2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1099,8 +1059,7 @@ static struct clk arm_fck = {
 	.clksel_reg	= OMAP3430_CM_IDLEST_PLL,
 	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
 	.clksel		= arm_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1114,8 +1073,7 @@ static struct clk arm_fck = {
 static struct clk emu_mpu_alwon_ck = {
 	.name		= "emu_mpu_alwon_ck",
 	.parent		= &mpu_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "mpu_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1128,8 +1086,7 @@ static struct clk dpll2_fck = {
 	.clksel_reg	= OMAP3430_CM_CLKSEL1_PLL,
 	.clksel_mask	= OMAP3430_IVA2_CLK_SRC_MASK,
 	.clksel		= div4_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "cm_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1141,7 +1098,7 @@ static struct clk iva2_ck = {
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm		= { .name = "iva2_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1161,8 +1118,7 @@ static struct clk l3_ick = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_L3_MASK,
 	.clksel		= div2_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1180,8 +1136,7 @@ static struct clk l4_ick = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_L4_MASK,
 	.clksel		= div2_l3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 
@@ -1235,8 +1190,7 @@ static struct clk gfx_l3_fck = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_l3_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "gfx_3430es1_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1407,8 +1361,7 @@ static struct clk usbtll_fck = {
 static struct clk core_96m_fck = {
 	.name		= "core_96m_fck",
 	.parent		= &omap_96m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1579,8 +1532,7 @@ static struct clk mcbsp1_fck = {
 static struct clk core_48m_fck = {
 	.name		= "core_48m_fck",
 	.parent		= &omap_48m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1679,8 +1631,7 @@ static struct clk fshostusb_fck = {
 static struct clk core_12m_fck = {
 	.name		= "core_12m_fck",
 	.parent		= &omap_12m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1723,7 +1674,7 @@ static struct clk ssi_ssr_fck_3430es1 = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1738,7 +1689,7 @@ static struct clk ssi_ssr_fck_3430es2 = {
 	.clksel_reg	= CM_CLKSEL,
 	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP3430ES2 | WAIT_READY,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1773,8 +1724,7 @@ static struct clk ssi_sst_fck_3430es2 = {
 static struct clk core_l3_ick = {
 	.name		= "core_l3_ick",
 	.parent		= &l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1828,8 +1778,7 @@ static struct clk gpmc_fck = {
 static struct clk security_l3_ick = {
 	.name		= "security_l3_ick",
 	.parent		= &l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l3_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -1851,8 +1800,7 @@ static struct clk pka_ick = {
 static struct clk core_l4_ick = {
 	.name		= "core_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2186,8 +2134,7 @@ static struct clk omapctrl_ick = {
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2247,8 +2194,7 @@ static struct clk usb_l4_ick = {
 static struct clk security_l4_ick2 = {
 	.name		= "security_l4_ick2",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "core_l4_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2518,7 +2464,7 @@ static struct clk gpt1_fck = {
 static struct clk wkup_32k_fck = {
 	.name		= "wkup_32k_fck",
 	.parent		= &omap_32k_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2550,7 +2496,7 @@ static struct clk wdt2_fck = {
 static struct clk wkup_l4_ick = {
 	.name		= "wkup_l4_ick",
 	.parent		= &sys_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2646,8 +2592,7 @@ static struct clk gpt1_ick = {
 static struct clk per_96m_fck = {
 	.name		= "per_96m_fck",
 	.parent		= &omap_96m_alwon_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2655,8 +2600,7 @@ static struct clk per_96m_fck = {
 static struct clk per_48m_fck = {
 	.name		= "per_48m_fck",
 	.parent		= &omap_48m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -2797,7 +2741,7 @@ static struct clk per_32k_alwon_fck = {
 	.name		= "per_32k_alwon_fck",
 	.parent		= &omap_32k_fck,
 	.clkdm		= { .name = "per_clkdm" },
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2876,8 +2820,7 @@ static struct clk wdt3_fck = {
 static struct clk per_l4_ick = {
 	.name		= "per_l4_ick",
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.clkdm		= { .name = "per_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -3229,7 +3172,7 @@ static struct clk emu_src_ck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3254,7 +3197,7 @@ static struct clk pclk_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_PCLK_MASK,
 	.clksel		= pclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3278,7 +3221,7 @@ static struct clk pclkx2_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_PCLKX2_MASK,
 	.clksel		= pclkx2_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3295,7 +3238,7 @@ static struct clk atclk_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_CLKSEL_ATCLK_MASK,
 	.clksel		= atclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3307,7 +3250,7 @@ static struct clk traceclk_src_fck = {
 	.clksel_reg	= CM_CLKSEL1,
 	.clksel_mask	= OMAP3430_TRACE_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm		= { .name = "emu_clkdm" },
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -3346,7 +3289,7 @@ static struct clk sr1_fck = {
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
 	.idlest_bit	= OMAP3430_ST_SR1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP343X | WAIT_READY,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
@@ -3359,7 +3302,7 @@ static struct clk sr2_fck = {
 	.enable_reg	= CM_FCLKEN,
 	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
 	.idlest_bit	= OMAP3430_ST_SR2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | WAIT_READY,
+	.flags		= CLOCK_IN_OMAP343X | WAIT_READY,
 	.clkdm		= { .name = "prm_clkdm" },
 	.recalc		= &followparent_recalc,
 };
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 358bf9e..a039832 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -153,16 +153,14 @@ 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 */
+/* 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 */
-#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 */
-- 
1.6.0.2.GIT


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-02-23 16:03                 ` Russell King - ARM Linux
  2009-02-24 12:35                   ` Woodruff, Richard
@ 2009-03-02 23:02                   ` Paul Walmsley
  2009-03-03 16:45                     ` Russell King - ARM Linux
  1 sibling, 1 reply; 50+ messages in thread
From: Paul Walmsley @ 2009-03-02 23:02 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Woodruff, Richard, linux-arm-kernel, linux-kernel, linux-omap,
	Tony Lindgren

Hello Russell,

On Mon, 23 Feb 2009, Russell King - ARM Linux wrote:

> On Thu, Feb 19, 2009 at 06:50:52PM -0600, Woodruff, Richard wrote:
> > The historic usage of this has been against single use leaf clocks (1st instance of gptimer).  When it was used it did:
> >         clk_get()
> >         clk_set_parent()
> >         clk_enable()
> > 
> > This usage was ok for that. Use on a disabled clock is needed.
> > 
> > If there are multiple users on the clock or it is enabled there are problems.
> 
> It sounds to me like clk_set_parent() needs this then to prevent enabled
> clocks being reparented.  By doing so, we no longer need to disable/enable
> the clock within the OMAP2/3 set_parent function since we are now
> guaranteed that the clock will be disabled.
> 
> Ack?

One suggestion on the patch:

> diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
> index 08baa18..b2d9e1f 100644
> --- a/arch/arm/plat-omap/clock.c
> +++ b/arch/arm/plat-omap/clock.c
> @@ -144,12 +144,14 @@ 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 (ret == 0) {
> -		if (clk->recalc)
> -			clk->rate = clk->recalc(clk);
> -		propagate_rate(clk);
> +	if (clk->usecount == 0) {
> +		if (arch_clock->clk_set_parent)
> +			ret = arch_clock->clk_set_parent(clk, parent);
> +		if (ret == 0) {
> +			if (clk->recalc)
> +				clk->rate = clk->recalc(clk);
> +			propagate_rate(clk);
> +		}
>  	}
>  	spin_unlock_irqrestore(&clockfw_lock, flags);

Suggest returning a more specific error than -EINVAL:

if (clk->usecount > 0)
        return -EBUSY;




- Paul

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH E 11/14] OMAP clock: track child clocks
  2009-03-02 23:02                   ` Paul Walmsley
@ 2009-03-03 16:45                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 50+ messages in thread
From: Russell King - ARM Linux @ 2009-03-03 16:45 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Woodruff, Richard, linux-arm-kernel, linux-kernel, linux-omap,
	Tony Lindgren

On Mon, Mar 02, 2009 at 04:02:14PM -0700, Paul Walmsley wrote:
> Suggest returning a more specific error than -EINVAL:
> 
> if (clk->usecount > 0)
>         return -EBUSY;

Done.

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2009-03-03 16:46 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-28 19:27 [PATCH E 00/14] OMAP clock, E of F: SDRAM fixes, clock optimization Paul Walmsley
2009-01-28 19:27 ` [PATCH E 01/14] OMAP2 SDRC: move mach-omap2/memory.h into include/asm-arm/arch-omap/sdrc.h Paul Walmsley
2009-01-28 19:27 ` [PATCH E 02/14] OMAP2 SDRC: rename memory.c to sdrc2xxx.c Paul Walmsley
2009-01-28 19:27 ` [PATCH E 03/14] OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code Paul Walmsley
2009-01-28 19:27 ` [PATCH E 04/14] OMAP2 SDRC: add SDRAM timing parameter infrastructure Paul Walmsley
2009-01-28 19:27 ` [PATCH E 05/14] OMAP3 clock: add omap3_core_dpll_m2_set_rate() Paul Walmsley
2009-01-28 19:27 ` [PATCH E 06/14] PM: OMAP3: Make sure clk_disable_unused() order is correct Paul Walmsley
2009-01-28 19:27 ` [PATCH E 07/14] OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init() Paul Walmsley
2009-01-28 19:27 ` [PATCH E 08/14] OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c Paul Walmsley
2009-01-29 17:41   ` Russell King - ARM Linux
2009-01-30  8:42     ` Paul Walmsley
2009-01-30  8:52       ` Russell King - ARM Linux
2009-01-30 14:23         ` Woodruff, Richard
2009-01-31 11:40           ` Russell King - ARM Linux
2009-02-03  8:42             ` Paul Walmsley
2009-02-03  9:45             ` Paul Walmsley
2009-02-02  7:13       ` Paul Walmsley
2009-02-03 13:18         ` Russell King - ARM Linux
2009-01-28 19:27 ` [PATCH E 09/14] OMAP2/3 clock: drop recalc function pointers from fixed rate clocks Paul Walmsley
2009-01-28 19:27 ` [PATCH E 10/14] OMAP clock: support "dry run" rate and parent changes Paul Walmsley
2009-02-08 13:17   ` Russell King - ARM Linux
2009-02-08 19:48     ` David Brownell
2009-02-11  7:53     ` Paul Walmsley
2009-02-08 15:53   ` Russell King - ARM Linux
2009-02-11  8:18     ` Paul Walmsley
2009-01-28 19:27 ` [PATCH E 11/14] OMAP clock: track child clocks Paul Walmsley
2009-01-29 15:14   ` Russell King - ARM Linux
2009-01-29 22:06     ` Russell King - ARM Linux
2009-01-30  8:35       ` Paul Walmsley
2009-02-02  4:57       ` Paul Walmsley
2009-02-09 14:11       ` Russell King - ARM Linux
2009-02-13  7:01         ` Paul Walmsley
2009-02-14 11:23           ` Russell King - ARM Linux
2009-02-14 11:36             ` Russell King - ARM Linux
2009-02-25  9:45               ` Paul Walmsley
2009-02-19 12:19             ` Russell King - ARM Linux
2009-02-20  0:50               ` Woodruff, Richard
2009-02-23 16:03                 ` Russell King - ARM Linux
2009-02-24 12:35                   ` Woodruff, Richard
2009-03-02 23:02                   ` Paul Walmsley
2009-03-03 16:45                     ` Russell King - ARM Linux
2009-02-22 23:37             ` Paul Walmsley
2009-02-24  9:43               ` Russell King - ARM Linux
2009-01-29 19:52   ` Russell King - ARM Linux
2009-02-02  7:57     ` Paul Walmsley
2009-01-28 19:28 ` [PATCH E 12/14] OMAP clock: unnecessary clock flag removal fiesta Paul Walmsley
2009-02-23 15:50   ` Russell King - ARM Linux
2009-03-02 22:35     ` Paul Walmsley
2009-01-28 19:28 ` [PATCH E 13/14] OMAP2/3 clock: remove clk->owner Paul Walmsley
2009-01-28 19:28 ` [PATCH E 14/14] OMAP clock: rearrange clock.h structure order Paul Walmsley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).