public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/28] omap2 clock: framework generalization, cleanup
@ 2007-08-20  9:53 Paul Walmsley
  2007-08-20  9:53 ` [PATCH 01/28] omap2 clock: dsp_ick parent is dsp_fck, not core_ck Paul Walmsley
                   ` (24 more replies)
  0 siblings, 25 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

Hello,

This set of patches contains some significant changes to the OMAP2 clock
framework.  The main goal of these patches is to generalize the framework
enough to be usable for the OMAP3430 clock tree, although in the process
I think the OMAP2 clock code is improved quite a bit - I hope you'll agree.

The major change in this patch set is the rewrite of clksel
clock handling, which: 

* enables clksel parent clocks to be updated at clock framework init, from
  whatever the bootloader configured,

* properly encodes platform restrictions for particular rates, 

* generalizes the clksel code to be useful for OMAP3430 clocks,

* facilitates future improved clock state reporting,

* and improves readability and maintainability.

The clksel patches are patches 6 through 20.  A few other notable changes 
in this patchset:

* Cleanups/bug fixes: patches 1, 3, 4, 5

* Generalize root clock propagation at clock framework init: patch 2

* Use OMAP clock framework enable/disable fns for osc_ck, APLLs: patches 21,
  22, 23

* Recalculate osc_ck and sys_ck via recalculate fns, rather than 
  omap2_get_crystal_rate(): patch 24

* Generalize DPLL multiplier, divider handling: patches 25

* Generalize clocks enabled at init via ENABLE_ON_INIT clock flag: patch 26

* Generalize clock autoidle configuration: patches 27, 28

The patches were boot-tested on N800.  Comments and testing are appreciated.
In particular, any testing on 2430SDP are particularly welcome, since I
don't have one here.

Patches apply cleanly against current git head, and seem to run fine,
but I've been doing most of my testing against 2.6.22-omap1, since my
N800 touchscreen does not work consistently with git head.

These changes increase uncompressed kernel memory footprint by 
about 6kB:
   text    data     bss     dec     hex filename
2877920  147788   85992 3111700  2f7b14 vmlinux.orig
2881092  150908   85992 3117992  2f93a8 vmlinux

diffstat:
 arch/arm/mach-omap2/clock.c                       |  978 +++++++++----------
 arch/arm/mach-omap2/clock.h                       | 1092 +++++++++++++++++-----
 arch/arm/plat-omap/clock.c                        |   20
 include/asm-arm/arch-omap/clock.h                 |   57 -
 linux-omap/arch/arm/mach-omap2/board-n800-audio.c |   13
 linux-omap/arch/arm/mach-omap2/clock.c            |    6
 linux-omap/arch/arm/mach-omap2/clock.h            |    2
 linux-omap/arch/arm/mach-omap2/cm_regbits_24xx.h  |   50 +
 linux-omap/arch/arm/mach-omap2/pm.c               |   63 -
 linux-omap/arch/arm/plat-omap/clock.c             |   17
 linux-omap/include/asm-arm/arch-omap/clock.h      |    1
 11 files changed, 1492 insertions(+), 807 deletions(-)

My apologies in advance for the double 'Index:' lines in some of the
patches - must be some quilt bug - it seems harmless and I have not
yet had the chance to track it down.

- Paul

-- 

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

* [PATCH 01/28] omap2 clock: dsp_ick parent is dsp_fck, not core_ck
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 02/28] omap2 clock: generalize initial clock rate setup: recalculate_root_clocks() Paul Walmsley
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: dsp_ick_uses_core_ck_as_parent.patch --]
[-- Type: text/plain, Size: 813 bytes --]

dsp_ick's parent clock is dsp_fck, not core_ck.  2420 TRM ES2.1.1 2.2 Rev Q 
pp. 4-9, 5-28.

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

---
 arch/arm/mach-omap2/clock.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-omap/arch/arm/mach-omap2/clock.h
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -820,7 +820,7 @@ static struct clk dsp_fck = {
 
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
-	.parent		= &dsp_fck,
+	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
 	.rate_offset	= OMAP24XX_CLKSEL_DSP_IF_SHIFT,

-- 

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

* [PATCH 02/28] omap2 clock: generalize initial clock rate setup: recalculate_root_clocks()
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
  2007-08-20  9:53 ` [PATCH 01/28] omap2 clock: dsp_ick parent is dsp_fck, not core_ck Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 03/28] omap2 clock: mark onchip_clks as __initdata Paul Walmsley
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add_propagate_roots.patch --]
[-- Type: text/plain, Size: 3850 bytes --]

Add a new clock framework function, recalculate_root_clocks(), that 
recalculates all root clocks (i.e., clocks with no parent clock).  
Call this function in omap2_clk_arch_init(), rather than manually
propagating specific clocks.  Add propagate_rate() recalcs to func_32k_ck
and osc_ck.

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

---
 arch/arm/mach-omap2/clock.c       |    6 ++----
 arch/arm/mach-omap2/clock.h       |    4 +++-
 arch/arm/plat-omap/clock.c        |   17 +++++++++++++++++
 include/asm-arm/arch-omap/clock.h |    1 +
 4 files changed, 23 insertions(+), 5 deletions(-)

Index: linux-omap/arch/arm/plat-omap/clock.c
Index: linux-omap/arch/arm/plat-omap/clock.c
===================================================================
--- linux-omap.orig/arch/arm/plat-omap/clock.c
+++ linux-omap/arch/arm/plat-omap/clock.c
@@ -312,6 +312,23 @@ void propagate_rate(struct clk * tclk)
 	}
 }
 
+/**
+ * recalculate_root_clocks - recalculate and propagate all root clocks
+ *
+ * Recalculates all root clocks (clocks with no parent), which if the
+ * clock's .recalc is set correctly, should also propagate their rates.
+ * Called at init.
+ */
+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);
+	}
+}
+
 int clk_register(struct clk *clk)
 {
 	if (clk == NULL || IS_ERR(clk))
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -57,6 +57,7 @@ extern int clk_init(struct clk_functions
 extern int clk_register(struct clk *clk);
 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 void clk_allow_idle(struct clk *clk);
 extern void clk_deny_idle(struct clk *clk);
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -1179,8 +1179,7 @@ static int __init omap2_clk_arch_init(vo
 	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
 		printk(KERN_ERR "Could not find matching MPU rate\n");
 
-	propagate_rate(&osc_ck);		/* update main root fast */
-	propagate_rate(&func_32k_ck);		/* update main root slow */
+	recalculate_root_clocks();
 
 	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
 	       "%ld.%01ld/%ld/%ld MHz\n",
@@ -1231,8 +1230,7 @@ int __init omap2_clk_init(void)
 	}
 	curr_prcm_set = prcm;
 
-	propagate_rate(&osc_ck);		/* update main root fast */
-	propagate_rate(&func_32k_ck);		/* update main root slow */
+	recalculate_root_clocks();
 
 	printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
 	       "%ld.%01ld/%ld/%ld MHz\n",
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -592,7 +592,8 @@ static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.rate		= 32000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED,
+				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+	.recalc		= &propagate_rate,
 };
 
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
@@ -601,6 +602,7 @@ static struct clk osc_ck = {		/* (*12, *
 	.rate		= 26000000,		/* fixed up in clock init */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | RATE_PROPAGATES,
+	.recalc		= &propagate_rate,
 };
 
 /* With out modem likely 12MHz, with modem likely 13MHz */

-- 

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

* [PATCH 03/28] omap2 clock: mark onchip_clks as __initdata
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
  2007-08-20  9:53 ` [PATCH 01/28] omap2 clock: dsp_ick parent is dsp_fck, not core_ck Paul Walmsley
  2007-08-20  9:53 ` [PATCH 02/28] omap2 clock: generalize initial clock rate setup: recalculate_root_clocks() Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 05/28] omap2 clock: rename, add comment to omap2_mpu_recalc() Paul Walmsley
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: mark_onchip_clks_initdata.patch --]
[-- Type: text/plain, Size: 719 bytes --]

The onchip_clks array is only used during init, so, mark it __initdata.

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

---
 arch/arm/mach-omap2/clock.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-omap/arch/arm/mach-omap2/clock.h
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -1988,7 +1988,7 @@ static struct clk virt_prcm_set = {
 	.round_rate	= &omap2_round_to_table_rate,
 };
 
-static struct clk *onchip_clks[] = {
+static struct clk *onchip_clks[] __initdata = {
 	/* external root sources */
 	&func_32k_ck,
 	&osc_ck,

-- 

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

* [PATCH 05/28] omap2 clock: rename, add comment to omap2_mpu_recalc()
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (2 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 03/28] omap2 clock: mark onchip_clks as __initdata Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 06/28] omap2 clock: add clksel and clksel_rate data Paul Walmsley
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: clarify_omap2_mpu_recalc.patch --]
[-- Type: text/plain, Size: 2201 bytes --]

omap2_mpu_recalc() actually just looks up what the MPU speed 'should'
currently be from the current virt_prcm_set rate set, rather than reporting
the actual hardware settings.  Clarify this by renaming it to 
omap2_table_mpu_recalc() and adding some comments.

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


---
 arch/arm/mach-omap2/clock.c |    9 +++++++--
 arch/arm/mach-omap2/clock.h |    4 ++--
 2 files changed, 9 insertions(+), 4 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -592,8 +592,13 @@ dpll_exit:
 	return(ret);
 }
 
-/* Just return the MPU speed */
-static void omap2_mpu_recalc(struct clk * clk)
+/**
+ * omap2_table_mpu_recalc - just return the MPU speed
+ * @clk: virt_prcm_set struct clk
+ *
+ * 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)
 {
 	clk->rate = curr_prcm_set->mpu_speed;
 }
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -24,7 +24,7 @@
 
 static void omap2_sys_clk_recalc(struct clk * clk);
 static void omap2_clksel_recalc(struct clk * clk);
-static void omap2_mpu_recalc(struct clk * clk);
+static void 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_clk_disable(struct clk *clk);
@@ -1982,7 +1982,7 @@ static struct clk virt_prcm_set = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
 	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
-	.recalc		= &omap2_mpu_recalc,	/* sets are keyed on mpu rate */
+	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
 	.set_rate	= &omap2_select_table_rate,
 	.round_rate	= &omap2_round_to_table_rate,
 };

-- 

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

* [PATCH 06/28] omap2 clock: add clksel and clksel_rate data
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (3 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 05/28] omap2 clock: rename, add comment to omap2_mpu_recalc() Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardware reality at clock init Paul Walmsley
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add-clksel-clksel_rate-data.patch --]
[-- Type: text/plain, Size: 36436 bytes --]

Many OMAP2 clocks are either source- or divisor-selectable by twiddling 
various register bits; these are 'clksel' clocks.  The table of rate divisors
and source clock settings was previously embedded in the clock.c source code.
Encode this data in two data structures:

1) struct clksel_rate for divisor-selection, mapping divisor values to 
register bit field values, along with a flags field indicating which 
chips the rate is available for -- one for each parent-rate combination; and:

2) struct clksel for source-selection, mapping parent struct clk pointers
to struct clksel_rate array pointers; one for each parent.

Also, add several fields to the clk structure:

1) clksel: pointer to the struct clksel array

2) clksel_reg: pointer to the clksel register

3) clksel_mask: mask for the clksel bitfield

Add this data to each clksel clock.  All this data is not yet used by the clock
framework; that functionality is in the following patches.

N.B. Two clocks, sys_clkout and sys_clkout2, could not be converted to
this setup without splitting source selection and divisor selection.
This is because these clocks use separate registers for each
selector.  So, create two new clocks, sys_clkout_src and
sys_clkout2_src, and locate source-selection there, and keep divisor
selection in sys_clkout/sys_clkout2.  This entailed modifying
board-n800-audio.c.


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

---
 arch/arm/mach-omap2/board-n800-audio.c |   13 
 arch/arm/mach-omap2/clock.h            |  536 ++++++++++++++++++++++++++++++++-
 include/asm-arm/arch-omap/clock.h      |   25 +
 3 files changed, 557 insertions(+), 17 deletions(-)

Index: linux-omap/include/asm-arm/arch-omap/clock.h
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -14,6 +14,22 @@
 #define __ARCH_ARM_OMAP_CLOCK_H
 
 struct module;
+struct clk;
+
+#if defined(CONFIG_ARCH_OMAP2)
+
+struct clksel_rate {
+	u8			div;
+	u32			val;
+	u8			flags;
+};
+
+struct clksel {
+	struct clk		 *parent;
+	const struct clksel_rate *rates;
+};
+
+#endif
 
 struct clk {
 	struct list_head	node;
@@ -36,6 +52,9 @@ struct clk {
 	void			(*disable)(struct clk *);
 #if defined(CONFIG_ARCH_OMAP2)
 	u8			fixed_div;
+	void __iomem		*clksel_reg;
+	u32			clksel_mask;
+	const struct clksel	*clksel;
 #endif
 };
 
@@ -94,6 +113,12 @@ extern int clk_get_usecount(struct clk *
 #define CLOCK_IN_OMAP343X	(1 << 27)
 #define PARENT_CONTROLS_CLOCK	(1 << 28)
 
+/* Clksel_rate flags */
+#define DEFAULT_RATE            (1 << 0)
+#define RATE_IN_242X            (1 << 1)
+#define RATE_IN_243X            (1 << 2)
+#define RATE_IN_343X            (1 << 3)
+#define RATE_IN_24XX            (RATE_IN_242X | RATE_IN_243X)
 
 
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -34,10 +34,6 @@ static u32 omap2_clksel_get_divisor(stru
 static void omap2_dpll_recalc(struct clk *clk);
 static void omap2_fixed_divisor_recalc(struct clk *clk);
 
-#define RATE_IN_242X	(1 << 0)
-#define RATE_IN_243X	(1 << 1)
-#define RATE_IN_343X	(1 << 2)
-
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
  * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -57,6 +53,8 @@ struct prcm_config {
 	unsigned char flags;
 };
 
+/* REVISIT: CM_PLL_SEL2 unused */
+
 /* Mask for clksel which support parent settign in set_rate */
 #define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \
 			CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1)
@@ -628,6 +626,9 @@ static struct clk alt_ck = {		/* Typical
  */
 
 /* dpll_ck, is broken out in to special cases through clksel */
+/* REVISIT: Rate changes on dpll_ck trigger a full set change.	...
+ * deal with this
+ */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
 	.parent		= &sys_ck,		/* Can be func_32k also */
@@ -662,6 +663,25 @@ static struct clk apll54_ck = {
 /*
  * PRCM digital base sources
  */
+
+/* func_54m_ck */
+
+static const struct clksel_rate func_54m_apll54_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate func_54m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel func_54m_clksel[] = {
+	{ .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
+	{ .parent = &alt_ck,	.rates = func_54m_alt_rates, },
+	{ .parent = NULL },
+};
+
 static struct clk func_54m_ck = {
 	.name		= "func_54m_ck",
 	.parent		= &apll54_ck,	/* can also be alt_clk */
@@ -670,6 +690,9 @@ static struct clk func_54m_ck = {
 				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_54M_SOURCE_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_54M_SOURCE,
+	.clksel		= func_54m_clksel,
 	.recalc		= &propagate_rate,
 };
 
@@ -681,6 +704,24 @@ static struct clk core_ck = {
 	.recalc		= &followparent_recalc,
 };
 
+/* func_96m_ck */
+static const struct clksel_rate func_96m_apll96_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate func_96m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_243X | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel func_96m_clksel[] = {
+	{ .parent = &apll96_ck,	.rates = func_96m_apll96_rates },
+	{ .parent = &alt_ck,	.rates = func_96m_alt_rates },
+	{ .parent = NULL }
+};
+
+/* The parent of this clock is not selectable on 2420. */
 static struct clk func_96m_ck = {
 	.name		= "func_96m_ck",
 	.parent		= &apll96_ck,
@@ -688,9 +729,30 @@ static struct clk func_96m_ck = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP2430_96M_SOURCE,
+	.clksel		= func_96m_clksel,
 	.recalc		= &propagate_rate,
 };
 
+/* func_48m_ck */
+
+static const struct clksel_rate func_48m_apll96_rates[] = {
+	{ .div = 2, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate func_48m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 },
+};
+
+static const struct clksel func_48m_clksel[] = {
+	{ .parent = &apll96_ck,	.rates	= func_48m_apll96_rates },
+	{ .parent = &alt_ck, .rates  = func_48m_alt_rates },
+	{ .parent = NULL }
+};
+
 static struct clk func_48m_ck = {
 	.name		= "func_48m_ck",
 	.parent		= &apll96_ck,	 /* 96M or Alt */
@@ -699,6 +761,9 @@ static struct clk func_48m_ck = {
 				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_48M_SOURCE_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_48M_SOURCE,
+	.clksel		= func_48m_clksel,
 	.recalc		= &propagate_rate,
 };
 
@@ -719,30 +784,116 @@ static struct clk wdt1_osc_ck = {
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sys_clkout = {
-	.name		= "sys_clkout",
+/*
+ * The common_clkout* clksel_rate structs are common to
+ * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
+ * sys_clkout2_* are 2420-only, so the
+ * clksel_rate flags fields are inaccurate for those clocks. This is
+ * harmless since access to those clocks are gated by the struct clk
+ * flags fields, which mark them as 2420-only.
+ */
+static const struct clksel_rate common_clkout_src_core_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_96m_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_54m_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel common_clkout_src_clksel[] = {
+	{ .parent = &core_ck,	  .rates = common_clkout_src_core_rates },
+	{ .parent = &sys_ck,	  .rates = common_clkout_src_sys_rates },
+	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
+	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
+	{ .parent = NULL }
+};
+
+static struct clk sys_clkout_src = {
+	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
 	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+				RATE_PROPAGATES,
 	.src_offset	= OMAP24XX_CLKOUT_SOURCE_SHIFT,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
+	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
+	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
+	.clksel		= common_clkout_src_clksel,
+	.recalc		= &propagate_rate,
+};
+
+static const struct clksel_rate common_clkout_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 8, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 16, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 0 },
+};
+
+static const struct clksel sys_clkout_clksel[] = {
+	{ .parent = &sys_clkout_src, .rates = common_clkout_rates },
+	{ .parent = NULL }
+};
+
+static struct clk sys_clkout = {
+	.name		= "sys_clkout",
+	.parent		= &sys_clkout_src,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+				PARENT_CONTROLS_CLOCK,
+	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
+	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
+	.clksel		= sys_clkout_clksel,
 	.rate_offset	= OMAP24XX_CLKOUT_DIV_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* In 2430, new in 2420 ES2 */
-static struct clk sys_clkout2 = {
-	.name		= "sys_clkout2",
+static struct clk sys_clkout2_src = {
+	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
-	.rate		= 54000000,
-	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
 	.src_offset	= OMAP2420_CLKOUT2_SOURCE_SHIFT,
+	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+				RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
+	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
+	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
+	.clksel		= common_clkout_src_clksel,
+	.recalc		= &propagate_rate,
+};
+
+static const struct clksel sys_clkout2_clksel[] = {
+	{ .parent = &sys_clkout2_src, .rates = common_clkout_rates },
+	{ .parent = NULL }
+};
+
+/* In 2430, new in 2420 ES2 */
+static struct clk sys_clkout2 = {
+	.name		= "sys_clkout2",
+	.parent		= &sys_clkout2_src,
+	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+				PARENT_CONTROLS_CLOCK,
+	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
+	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
+	.clksel		= sys_clkout2_clksel,
 	.rate_offset	= OMAP2420_CLKOUT2_DIV_SHIFT,
-	.recalc		= &omap2_clksel_recalc,
+	.recalc		= &propagate_rate,
 };
 
 static struct clk emul_ck = {
@@ -765,6 +916,20 @@ static struct clk emul_ck = {
  * - Base divider comes from: CM_CLKSEL_MPU
  *
  */
+static const struct clksel_rate mpu_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 0 },
+};
+
+static const struct clksel mpu_clksel[] = {
+	{ .parent = &core_ck, .rates = mpu_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk mpu_ck = {	/* Control cpu */
 	.name		= "mpu_ck",
 	.parent		= &core_ck,
@@ -772,6 +937,9 @@ static struct clk mpu_ck = {	/* Control 
 				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.rate_offset	= OMAP24XX_CLKSEL_MPU_SHIFT,	/* bits 0-4 */
+	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
+	.clksel		= mpu_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -781,6 +949,27 @@ static struct clk mpu_ck = {	/* Control 
  *	2430: IVA2.1_FCLK, IVA2.1_ICLK
  *	2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
  */
+/* XXX Okay, this is dumb.  iva2_1fck and dsp_fck are the same clock.
+ * they should just be treated as such.
+ */
+
+/* iva2_1_fck */
+static const struct clksel_rate iva2_1_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 0 },
+};
+
+static const struct clksel iva2_1_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = iva2_1_fck_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk iva2_1_fck = {
 	.name		= "iva2_1_fck",
 	.parent		= &core_ck,
@@ -790,15 +979,34 @@ static struct clk iva2_1_fck = {
 	.rate_offset	= OMAP24XX_CLKSEL_DSP_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
+	.clksel		= iva2_1_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* iva2_1_ick */
+static const struct clksel_rate iva2_1_ick_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 0 },
+};
+
+static const struct clksel iva2_1_ick_clksel[] = {
+	{ .parent = &core_ck, .rates = iva2_1_ick_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.parent		= &iva2_1_fck,
 	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
 	.rate_offset	= OMAP24XX_CLKSEL_DSP_IF_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= iva2_1_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -808,6 +1016,22 @@ static struct clk iva2_1_ick = {
  * controls. The other branch gets further divided by 2 then possibly
  * routed into a synchronizer and out of clocks abc.
  */
+static const struct clksel_rate dsp_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 0 },
+};
+
+static const struct clksel dsp_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk dsp_fck = {
 	.name		= "dsp_fck",
 	.parent		= &core_ck,
@@ -816,9 +1040,24 @@ static struct clk dsp_fck = {
 	.rate_offset	= OMAP24XX_CLKSEL_DSP_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
+	.clksel		= dsp_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate dsp_ick_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 0 },
+};
+
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &core_ck, .rates = dsp_ick_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
 	.parent		= &core_ck,
@@ -827,9 +1066,28 @@ static struct clk dsp_ick = {
 	.rate_offset	= OMAP24XX_CLKSEL_DSP_IF_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,		/* for ipi */
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate iva1_ifck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_242X | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
+	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 0 },
+};
+
+static const struct clksel iva1_ifck_clksel[] = {
+	{ .parent = &core_ck, .rates = iva1_ifck_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
@@ -838,6 +1096,9 @@ static struct clk iva1_ifck = {
 	.rate_offset	= OMAP2420_CLKSEL_IVA_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP2420_CLKSEL_IVA_MASK,
+	.clksel		= iva1_ifck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -871,6 +1132,22 @@ static struct clk iva1_mpu_int_ifck = {
  * may very well need notification when the clock changes. Currently for low
  * operating points, these are taken care of in sleep.S.
  */
+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 },
+	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel core_l3_clksel[] = {
+	{ .parent = &core_ck, .rates = core_l3_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
 	.name		= "core_l3_ck",
 	.parent		= &core_ck,
@@ -879,9 +1156,25 @@ static struct clk core_l3_ck = {	/* Used
 				DELAYED_APP | CONFIG_PARTICIPANT |
 				RATE_PROPAGATES,
 	.rate_offset	= OMAP24XX_CLKSEL_L3_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
+	.clksel		= core_l3_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* usb_l4_ick */
+static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel usb_l4_ick_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
+	{ .parent = NULL },
+};
+
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
 	.parent		= &core_l3_ck,
@@ -891,6 +1184,9 @@ static struct clk usb_l4_ick = {	/* FS-U
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
 	.rate_offset	= OMAP24XX_CLKSEL_USB_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
+	.clksel		= usb_l4_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -902,6 +1198,22 @@ static struct clk usb_l4_ick = {	/* FS-U
  *
  * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
  */
+static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_243X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel ssi_ssr_sst_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk ssi_ssr_sst_fck = {
 	.name		= "ssi_fck",
 	.parent		= &core_ck,
@@ -909,6 +1221,9 @@ static struct clk ssi_ssr_sst_fck = {
 				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),	/* bit 1 */
 	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
+	.clksel		= ssi_ssr_sst_fck_clksel,
 	.rate_offset	= OMAP24XX_CLKSEL_SSI_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -924,6 +1239,25 @@ static struct clk ssi_ssr_sst_fck = {
  * divided value of fclk.
  *
  */
+/* XXX REVISIT: GFX clock is part of CONFIG_PARTICIPANT, no? doublecheck. */
+
+/*
+ * These clksel_rate/clksel structs are shared between gfx_3d_fck and
+ * gfx_2d_fck
+ */
+static const struct clksel_rate gfx_fck_core_l3_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_243X },
+	{ .div = 0 }
+};
+
+static const struct clksel gfx_fck_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = gfx_fck_core_l3_rates },
+	{ .parent = NULL },
+};
+
 static struct clk gfx_3d_fck = {
 	.name		= "gfx_3d_fck",
 	.parent		= &core_l3_ck,
@@ -932,6 +1266,9 @@ static struct clk gfx_3d_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
 	.rate_offset	= OMAP_CLKSEL_GFX_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
+	.clksel		= gfx_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -943,6 +1280,9 @@ static struct clk gfx_2d_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
 	.rate_offset	= OMAP_CLKSEL_GFX_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
+	.clksel		= gfx_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -962,6 +1302,19 @@ static struct clk gfx_ick = {
  *		MDM_ICLK
  * These clocks are usable in chassis mode only.
  */
+static const struct clksel_rate mdm_ick_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_243X | DEFAULT_RATE },
+	{ .div = 6, .val = 6, .flags = RATE_IN_243X },
+	{ .div = 9, .val = 9, .flags = RATE_IN_243X },
+	{ .div = 0 }
+};
+
+static const struct clksel mdm_ick_clksel[] = {
+	{ .parent = &core_ck, .rates = mdm_ick_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
 	.parent		= &core_ck,
@@ -970,6 +1323,9 @@ static struct clk mdm_ick = {		/* used b
 	.rate_offset	= OMAP2430_CLKSEL_MDM_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP2430_CLKSEL_MDM_MASK,
+	.clksel		= mdm_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -989,6 +1345,17 @@ static struct clk mdm_osc_ck = {
  * functional clocks.	Fixed APLL functional source clocks are managed in
  * this domain.
  */
+static const struct clksel_rate l4_core_l3_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel l4_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = l4_core_l3_rates },
+	{ .parent = NULL }
+};
+
 static struct clk l4_ck = {		/* used both as an ick and fck */
 	.name		= "l4_ck",
 	.parent		= &core_l3_ck,
@@ -996,6 +1363,9 @@ static struct clk l4_ck = {		/* used bot
 				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
 				DELAYED_APP | RATE_PROPAGATES,
 	.rate_offset	= OMAP24XX_CLKSEL_L4_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
+	.clksel		= l4_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -1016,6 +1386,33 @@ static struct clk ssi_l4_ick = {
  *
  * DSS is both initiator and target.
  */
+/* XXX Add RATE_NOT_VALIDATED */
+
+static const struct clksel_rate dss1_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss1_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
+	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
+	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
+	{ .div = 16, .val = 16, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel dss1_fck_clksel[] = {
+	{ .parent = &sys_ck, .rates  = dss1_fck_sys_rates },
+	{ .parent = &core_ck,.rates  = dss1_fck_core_rates },
+	{ .parent = NULL },
+};
+
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
 	.parent		= &l4_ck,	/* really both l3 and l4 */
@@ -1034,9 +1431,28 @@ static struct clk dss1_fck = {
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
 	.rate_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
+	.clksel		= dss1_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate dss2_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss2_fck_48m_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel dss2_fck_clksel[] = {
+	{ .parent = &sys_ck,	  .rates = dss2_fck_sys_rates },
+	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
+	{ .parent = NULL }
+};
+
 static struct clk dss2_fck = {		/* Alt clk used in power management */
 	.name		= "dss2_fck",
 	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
@@ -1046,6 +1462,9 @@ static struct clk dss2_fck = {		/* Alt c
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_DSS2_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
+	.clksel		= dss2_fck_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1064,6 +1483,28 @@ static struct clk dss_54m_fck = {	/* Alt
  * here will likely have an L4 interface parent, and may have multiple
  * functional clock parents.
  */
+static const struct clksel_rate gpt_32k_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate gpt_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate gpt_alt_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel gpt_clksel[] = {
+	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
+	{ .parent = &sys_ck,	  .rates = gpt_sys_rates },
+	{ .parent = &alt_ck,	  .rates = gpt_alt_rates },
+	{ .parent = NULL },
+};
+
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
 	.parent		= &l4_ck,
@@ -1081,6 +1522,9 @@ static struct clk gpt1_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, OMAP24XX_CM_FCLKEN),	/* Bit0 */
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT1_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1101,6 +1545,9 @@ static struct clk gpt2_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT2_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1121,6 +1568,9 @@ static struct clk gpt3_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT3_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1141,6 +1591,9 @@ static struct clk gpt4_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT4_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1161,6 +1614,9 @@ static struct clk gpt5_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT5_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1168,8 +1624,8 @@ static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit8 */
+	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1181,6 +1637,9 @@ static struct clk gpt6_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT6_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1201,6 +1660,9 @@ static struct clk gpt7_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT7_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1221,6 +1683,9 @@ static struct clk gpt8_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT8_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1241,6 +1706,9 @@ static struct clk gpt9_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT9_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1261,6 +1729,9 @@ static struct clk gpt10_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT10_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1281,6 +1752,9 @@ static struct clk gpt11_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT11_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1301,15 +1775,17 @@ static struct clk gpt12_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT12_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
+	.clksel		= gpt_clksel,
 	.recalc		= &followparent_recalc,
 };
 
-/* REVISIT: bit comment below wrong? */
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit16 */
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
@@ -1800,6 +2276,31 @@ static struct clk vlynq_ick = {
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel_rate vlynq_fck_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_242X | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate vlynq_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_242X },
+	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
+	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 9, .val = 9, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 16, .val = 16, .flags = RATE_IN_242X | DEFAULT_RATE },
+	{ .div = 18, .val = 18, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel vlynq_fck_clksel[] = {
+	{ .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
+	{ .parent = &core_ck,	  .rates = vlynq_fck_core_rates },
+	{ .parent = NULL }
+};
+
 static struct clk vlynq_fck = {
 	.name		= "vlynq_fck",
 	.parent		= &func_96m_ck,
@@ -1807,6 +2308,9 @@ static struct clk vlynq_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
 	.src_offset	= OMAP2420_CLKSEL_VLYNQ_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
+	.clksel		= vlynq_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -2004,7 +2508,9 @@ static struct clk *onchip_clks[] __initd
 	&func_48m_ck,
 	&func_12m_ck,
 	&wdt1_osc_ck,
+	&sys_clkout_src,
 	&sys_clkout,
+	&sys_clkout2_src,
 	&sys_clkout2,
 	&emul_ck,
 	/* mpu domain clocks */
Index: linux-omap/arch/arm/mach-omap2/board-n800-audio.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/board-n800-audio.c
+++ linux-omap/arch/arm/mach-omap2/board-n800-audio.c
@@ -35,6 +35,7 @@
 #define AUDIO_ENABLED
 
 static struct clk *sys_clkout2;
+static struct clk *sys_clkout2_src;
 static struct clk *func96m_clk;
 static struct device *eac_device;
 static struct device *tsc2301_device;
@@ -186,9 +187,15 @@ static void n800_eac_cleanup(struct devi
 
 static int n800_codec_get_clocks(struct device *dev)
 {
+	sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
+	if (IS_ERR(sys_clkout2_src)) {
+		dev_err(dev, "Could not get sys_clkout2_src clock\n");
+		return -ENODEV;
+	}
 	sys_clkout2 = clk_get(dev, "sys_clkout2");
 	if (IS_ERR(sys_clkout2)) {
-		dev_err(dev, "Could not get sys_clkout2\n");
+		dev_err(dev, "Could not get sys_clkout2 clock\n");
+		clk_put(sys_clkout2_src);
 		return -ENODEV;
 	}
 	/* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
@@ -197,10 +204,11 @@ static int n800_codec_get_clocks(struct 
 	if (IS_ERR(func96m_clk)) {
 		dev_err(dev, "Could not get func 96M clock\n");
 		clk_put(sys_clkout2);
+		clk_put(sys_clkout2_src);
 		return -ENODEV;
 	}
 
-	clk_set_parent(sys_clkout2, func96m_clk);
+	clk_set_parent(sys_clkout2_src, func96m_clk);
 	clk_set_rate(sys_clkout2, 12000000);
 
 	return 0;
@@ -210,6 +218,7 @@ static void n800_codec_put_clocks(struct
 {
 	clk_put(func96m_clk);
 	clk_put(sys_clkout2);
+	clk_put(sys_clkout2_src);
 }
 
 static int n800_codec_enable_clock(struct device *dev)

-- 

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

* [PATCH 07/28] omap2 clock: init clksel clock parents to hardware reality at clock init
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (4 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 06/28] omap2 clock: add clksel and clksel_rate data Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20 12:27   ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardwarereality " Woodruff, Richard
  2007-08-20  9:53 ` [PATCH 08/28] omap2 clock: convert omap2_clksel_to_divisor and omap2_divisor_to_clksel to use new clksel struct Paul Walmsley
                   ` (18 subsequent siblings)
  24 siblings, 1 reply; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add_init_clksel_parent.patch --]
[-- Type: text/plain, Size: 11555 bytes --]

Source-selectable clksel clocks have a 'default parent' assigned to them
at compile-time.  This default parent may or may not match the reality 
that is configured in the hardware registers by the bootloader.  Clock tree
recalculations could be erratic if the struct clk parent field contents
don't match the hardware registers.

Resolve this by creating omap2_init_clksel_parent() to read the hardware
registers and update the struct clk parent field as appropriate for clksel
clocks.  Add an '.init' field to each source-selectable clk structure so
that the parent is fixed up when the clock is initially registered.  (We
don't do this for clksel clocks that are only rate-selectable, since they
only have one possible parent clock.)

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

---
 arch/arm/mach-omap2/clock.c |   58 ++++++++++++++++++++++++++++++++++++++++----
 arch/arm/mach-omap2/clock.h |   22 ++++++++++++++++
 2 files changed, 75 insertions(+), 5 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -93,6 +93,54 @@ static u32 sysclkout_div[] = {1, 2, 4, 8
  * Omap2 specific clock functions
  *-------------------------------------------------------------------------*/
 
+static inline u8 convert_mask_to_shift(u32 mask) {
+	return ffs(mask) - 1;
+}
+
+/**
+ * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
+ * @clk: OMAP clock struct ptr to use
+ *
+ * Given a pointer to a source-selectable struct clk, read the hardware
+ * register and determine what its parent is currently set to.  Update the
+ * clk->parent field with the appropriate clk ptr.
+ */
+static void omap2_init_clksel_parent(struct clk *clk)
+{
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+	u32 r, found = 0;
+
+	if (!clk->clksel)
+		return;
+
+	/* XXX Should be __raw_readl for non-CM 3430 clocks ? */
+	r = cm_read_reg(clk->clksel_reg) & clk->clksel_mask;
+	r >>= convert_mask_to_shift(clk->clksel_mask);
+
+	for (clks = clk->clksel; clks->parent && !found; clks++) {
+		for (clkr = clks->rates; clkr->div && !found; clkr++) {
+			if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
+				if (clk->parent != clks->parent) {
+					pr_debug("clock: inited %s parent "
+						 "to %s (was %s)\n",
+						 clk->name, clks->parent->name,
+						 ((clk->parent->name) ?
+						  clk->parent->name : "NULL"));
+					clk->parent = clks->parent;
+				};
+				found = 1;
+			}
+		}
+	}
+
+	if (!found)
+		printk(KERN_ERR "clock: init parent: could not find "
+		       "regval %0x for clock %s\n", r,  clk->name);
+
+	return;
+}
+
 /* Recalculate SYST_CLK */
 static void omap2_sys_clk_recalc(struct clk * clk)
 {
@@ -1193,6 +1241,11 @@ int __init omap2_clk_init(void)
 	struct clk ** clkp;
 	u32 clkrate;
 
+	if (cpu_is_omap242x())
+		cpu_mask = RATE_IN_242X;
+	else if (cpu_is_omap2430())
+		cpu_mask = RATE_IN_243X;
+
 	clk_init(&omap2_clk_functions);
 	omap2_get_crystal_rate(&osc_ck, &sys_ck);
 
@@ -1210,11 +1263,6 @@ int __init omap2_clk_init(void)
 		}
 	}
 
-	if (cpu_is_omap242x())
-		cpu_mask = RATE_IN_242X;
-	else if (cpu_is_omap2430())
-		cpu_mask = RATE_IN_243X;
-
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2_get_dpll_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -29,6 +29,7 @@ static int omap2_select_table_rate(struc
 static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
 static void omap2_clk_disable(struct clk *clk);
 static void omap2_sys_clk_recalc(struct clk * clk);
+static void omap2_init_clksel_parent(struct clk *clk);
 static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
 static u32 omap2_clksel_get_divisor(struct clk *clk);
 static void omap2_dpll_recalc(struct clk *clk);
@@ -690,6 +691,7 @@ static struct clk func_54m_ck = {
 				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_54M_SOURCE_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_54M_SOURCE,
 	.clksel		= func_54m_clksel,
@@ -729,6 +731,7 @@ static struct clk func_96m_ck = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP2430_96M_SOURCE,
 	.clksel		= func_96m_clksel,
@@ -761,6 +764,7 @@ static struct clk func_48m_ck = {
 				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_48M_SOURCE_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_48M_SOURCE,
 	.clksel		= func_48m_clksel,
@@ -830,6 +834,7 @@ static struct clk sys_clkout_src = {
 	.src_offset	= OMAP24XX_CLKOUT_SOURCE_SHIFT,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
 	.clksel		= common_clkout_src_clksel,
@@ -872,6 +877,7 @@ static struct clk sys_clkout2_src = {
 				RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
 	.clksel		= common_clkout_src_clksel,
@@ -937,6 +943,7 @@ static struct clk mpu_ck = {	/* Control 
 				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.rate_offset	= OMAP24XX_CLKSEL_MPU_SHIFT,	/* bits 0-4 */
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
 	.clksel		= mpu_clksel,
@@ -1431,6 +1438,7 @@ static struct clk dss1_fck = {
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
 	.rate_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
 	.clksel		= dss1_fck_clksel,
@@ -1462,6 +1470,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_DSS2_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
 	.clksel		= dss2_fck_clksel,
@@ -1522,6 +1531,7 @@ static struct clk gpt1_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, OMAP24XX_CM_FCLKEN),	/* Bit0 */
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT1_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
 	.clksel		= gpt_clksel,
@@ -1545,6 +1555,7 @@ static struct clk gpt2_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT2_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
 	.clksel		= gpt_clksel,
@@ -1568,6 +1579,7 @@ static struct clk gpt3_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT3_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
 	.clksel		= gpt_clksel,
@@ -1591,6 +1603,7 @@ static struct clk gpt4_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT4_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
 	.clksel		= gpt_clksel,
@@ -1614,6 +1627,7 @@ static struct clk gpt5_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT5_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
 	.clksel		= gpt_clksel,
@@ -1637,6 +1651,7 @@ static struct clk gpt6_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT6_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
 	.clksel		= gpt_clksel,
@@ -1660,6 +1675,7 @@ static struct clk gpt7_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT7_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
 	.clksel		= gpt_clksel,
@@ -1683,6 +1699,7 @@ static struct clk gpt8_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT8_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
 	.clksel		= gpt_clksel,
@@ -1706,6 +1723,7 @@ static struct clk gpt9_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT9_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
 	.clksel		= gpt_clksel,
@@ -1729,6 +1747,7 @@ static struct clk gpt10_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT10_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
 	.clksel		= gpt_clksel,
@@ -1752,6 +1771,7 @@ static struct clk gpt11_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT11_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
 	.clksel		= gpt_clksel,
@@ -1775,6 +1795,7 @@ static struct clk gpt12_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_GPT12_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
 	.clksel		= gpt_clksel,
@@ -2308,6 +2329,7 @@ static struct clk vlynq_fck = {
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
 	.src_offset	= OMAP2420_CLKSEL_VLYNQ_SHIFT,
+	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
 	.clksel		= vlynq_fck_clksel,

-- 

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

* [PATCH 08/28] omap2 clock: convert omap2_clksel_to_divisor and omap2_divisor_to_clksel to use new clksel struct
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (5 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardware reality at clock init Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 09/28] omap2 clock: convert omap2_clksel_round_rate " Paul Walmsley
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add_gcbp_convert_c2d_d2c.patch --]
[-- Type: text/plain, Size: 6602 bytes --]

Convert omap2_clksel_to_divisor() and omap2_divisor_to_clksel() to use
the new struct clksel and struct clksel_rate data.  Add 
omap2_get_clksel_by_parent() utility code, called by both functions, 
to return the appropriate struct clksel for a given (struct clk, parent 
struct clk) combination.

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

---
 arch/arm/mach-omap2/clock.c |  132 +++++++++++++++++++++++++++++++++-----------
 arch/arm/mach-omap2/clock.h |    3 -
 2 files changed, 102 insertions(+), 33 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -497,6 +497,38 @@ static inline u32 omap2_divider_from_tab
 	return ~0;	/* No acceptable divider */
 }
 
+/**
+ * omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
+ * @clk: OMAP struct clk ptr to inspect
+ * @src_clk: OMAP struct clk ptr of the parent clk to search for
+ *
+ * Scan the struct clksel array associated with the clock to find
+ * the element associated with the supplied parent clock address.
+ * Returns a pointer to the struct clksel on success or NULL on error.
+ */
+const static struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
+						       struct clk *src_clk)
+{
+	const struct clksel *clks;
+
+	if (!clk->clksel)
+		return NULL;
+
+	for (clks = clk->clksel; clks->parent; clks++) {
+		if (clks->parent == src_clk)
+			break; /* Found the requested parent */
+	}
+
+	if (!clks->parent) {
+		printk(KERN_ERR "clock: Could not find parent clock %s in "
+		       "clksel array of clock %s\n", src_clk->name,
+		       clk->name);
+		return NULL;
+	}
+
+	return clks;
+}
+
 /*
  * Find divisor for the given clock and target rate.
  *
@@ -683,38 +715,74 @@ static long omap2_round_to_table_rate(st
 	return highest_rate;
 }
 
-/*
- * omap2_clksel_to_divisor() - turn field value into integer divider
+/**
+ * omap2_clksel_to_divisor() - turn clksel field value into integer divider
+ * @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
+ * field value should be pre-masked and shifted down so the LSB is at bit 0
+ * before calling.  Returns 0 on error
  */
-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
+static u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
 {
-	u32 i;
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
 
-	if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
-		for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
-			if (field_val == i)
-				return sysclkout_div[i];
-		}
+	clks = omap2_get_clksel_by_parent(clk, clk->parent);
+	if (clks == NULL)
 		return 0;
-	} else
-		return field_val;
+
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
+			break;
+	}
+
+	if (!clkr->div) {
+		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 clkr->div;
 }
 
-/*
- * omap2_divisor_to_clksel() - turn integer divider into field value
+/**
+ * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
+ * @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 0xffffffff on error
  */
-static u32 omap2_divisor_to_clksel(u32 div_sel, u32 div)
+static u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 {
-	u32 i;
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+
+	/* should never happen */
+	WARN_ON(div == 0);
 
-	if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
-		for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
-			if (div == sysclkout_div[i])
-				return i;
-		}
-		return ~0;
-	} else
-		return div;
+	clks = omap2_get_clksel_by_parent(clk, clk->parent);
+	if (clks == NULL)
+		return 0;
+
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if ((clkr->flags & cpu_mask) && (clkr->div == div))
+			break;
+	}
+
+	if (!clkr->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 clkr->val;
 }
 
 /*
@@ -800,13 +868,15 @@ static void __iomem *omap2_get_clksel(u3
 }
 
 
-/*
- * Return divider to be applied to parent clock.
- * Return 0 on error.
+/**
+ * omap2_clksel_get_divisor - get current divider applied to parent clock.
+ * @clk: OMAP struct clk to use.
+ *
+ * Returns the integer divisor upon success or 0 on error.
  */
 static u32 omap2_clksel_get_divisor(struct clk *clk)
 {
-	u32 div, field_mask, field_val;
+	u32 field_mask, field_val;
 	void __iomem *div_addr;
 
 	div_addr = omap2_get_clksel(&field_mask, clk);
@@ -814,11 +884,9 @@ static u32 omap2_clksel_get_divisor(stru
 		return 0;
 
 	field_val = cm_read_reg(div_addr) & field_mask;
-	field_val >>= clk->rate_offset;
-
-	div = omap2_clksel_to_divisor(clk->flags, field_val);
+	field_val >>= convert_mask_to_shift(field_mask);
 
-	return div;
+	return omap2_clksel_to_divisor(clk, field_val);
 }
 
 /* Set the clock rate for a clock source */
@@ -844,7 +912,7 @@ static int omap2_clk_set_rate(struct clk
 		if (div_addr == 0)
 			return ret;
 
-		field_val = omap2_divisor_to_clksel(clk->flags, new_div);
+		field_val = omap2_divisor_to_clksel(clk, new_div);
 		if (field_val == ~0)
 			return ret;
 
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -30,8 +30,9 @@ static long omap2_round_to_table_rate(st
 static void omap2_clk_disable(struct clk *clk);
 static void omap2_sys_clk_recalc(struct clk * clk);
 static void omap2_init_clksel_parent(struct clk *clk);
-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
 static u32 omap2_clksel_get_divisor(struct clk *clk);
+static u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
+static u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
 static void omap2_dpll_recalc(struct clk *clk);
 static void omap2_fixed_divisor_recalc(struct clk *clk);
 

-- 

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

* [PATCH 09/28] omap2 clock: convert omap2_clksel_round_rate to use new clksel struct
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (6 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 08/28] omap2 clock: convert omap2_clksel_to_divisor and omap2_divisor_to_clksel to use new clksel struct Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 10/28] omap2 clock: convert omap2_get_clksel " Paul Walmsley
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_clksel_round_rate.patch --]
[-- Type: text/plain, Size: 4175 bytes --]

Convert omap2_clksel_round_rate() to use the new clksel struct data.

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

---
 arch/arm/mach-omap2/clock.c |   98 ++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 48 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -87,8 +87,6 @@ static struct clk *vclk;
 static struct clk *sclk;
 static u8 cpu_mask;
 
-static u32 sysclkout_div[] = {1, 2, 4, 8, 16};
-
 /*-------------------------------------------------------------------------
  * Omap2 specific clock functions
  *-------------------------------------------------------------------------*/
@@ -529,62 +527,66 @@ const static struct clksel *omap2_get_cl
 	return clks;
 }
 
-/*
- * Find divisor for the given clock and target rate.
+/**
+ * omap2_clksel_round_rate - find divisor for the given clock and target rate.
+ * @clk: OMAP struct clk to use
+ * @target_rate: desired clock rate
+ * @new_div: ptr to where we should store the divisor
  *
+ * 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.
  */
-static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
-	u32 *new_div)
+static u32 omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate,
+				   u32 *new_div)
 {
-	u32 gfx_div[] = {2, 3, 4};
-	u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
-	u32 vlynq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
-	u32 best_div = ~0, asize = 0;
-	u32 *div_array = NULL;
+	unsigned long test_rate;
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+	u32 last_div = 0;
 
-	switch (tclk->flags & SRC_RATE_SEL_MASK) {
-	case CM_GFX_SEL1:
-		asize = ARRAY_SIZE(gfx_div);
-		div_array = gfx_div;
-		break;
-	case CM_PLL_SEL1:
-		return omap2_dpll_round_rate(target_rate);
-	case CM_SYSCLKOUT_SEL1:
-		asize = ARRAY_SIZE(sysclkout_div);
-		div_array = sysclkout_div;
-		break;
-	case CM_CORE_SEL1:
-		if (tclk == &dss1_fck) {
-			if (tclk->parent == &core_ck) {
-				asize = ARRAY_SIZE(dss1_div);
-				div_array = dss1_div;
-			} else {
-				*new_div = 0; /* fixed clk */
-				return(tclk->parent->rate);
-			}
-		} else if ((tclk == &vlynq_fck) && cpu_is_omap2420()) {
-			if (tclk->parent == &core_ck) {
-				asize = ARRAY_SIZE(vlynq_div);
-				div_array = vlynq_div;
-			} else {
-				*new_div = 0; /* fixed clk */
-				return (tclk->parent->rate);
-			}
-		}
-		break;
+	printk(KERN_INFO "clock: clksel_round_rate for %s target_rate %ld\n",
+	       clk->name, target_rate);
+
+	*new_div = 1;
+
+	clks = omap2_get_clksel_by_parent(clk, clk->parent);
+	if (clks == NULL)
+		return ~0;
+
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if (!(clkr->flags & cpu_mask))
+		    continue;
+
+		/* Sanity check */
+		if (clkr->div <= last_div)
+			printk(KERN_ERR "clock: clksel_rate table not sorted "
+			       "for clock %s", clk->name);
+
+		last_div = clkr->div;
+
+		test_rate = clk->parent->rate / clkr->div;
+
+		if (test_rate <= target_rate)
+			break; /* found it */
 	}
 
-	best_div = omap2_divider_from_table(asize, div_array,
-					    tclk->parent->rate, target_rate);
-	if (best_div == ~0) {
-		*new_div = 1;
-		return best_div; /* signal error */
+	if (!clkr->div) {
+		printk(KERN_ERR "clock: Could not find divisor for target "
+		       "rate %ld for clock %s parent %s\n", target_rate,
+		       clk->name, clk->parent->name);
+		return ~0;
 	}
 
-	*new_div = best_div;
-	return (tclk->parent->rate / best_div);
+	*new_div = clkr->div;
+
+	printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div,
+	       (clk->parent->rate / clkr->div));
+
+	return (clk->parent->rate / clkr->div);
 }
 
 /* Given a clock and a rate apply a clock specific rounding function */

-- 

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

* [PATCH 10/28] omap2 clock: convert omap2_get_clksel to use new clksel struct
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (7 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 09/28] omap2 clock: convert omap2_clksel_round_rate " Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 11/28] omap2 clock: convert omap2_clksel_get_src_field() " Paul Walmsley
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_get_clksel.patch --]
[-- Type: text/plain, Size: 4158 bytes --]

Convert omap2_get_clksel to use new struct clksel and struct
clksel_rate data.  Also fix its parameter order to conform with the
rest of the clock framework functions (i.e., struct clk first).

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

---
 arch/arm/mach-omap2/clock.c |   92 ++++++--------------------------------------
 1 file changed, 13 insertions(+), 79 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -787,89 +787,23 @@ static u32 omap2_divisor_to_clksel(struc
 	return clkr->val;
 }
 
-/*
- * Returns the CLKSEL divider register value
+/**
+ * omap2_get_clksel - find clksel register addr & field mask for a clk
+ * @clk: struct clk to use
+ * @field_mask: ptr to u32 to store the register field mask
+ *
+ * Returns the address of the clksel register upon success or NULL on error.
  */
-static void __iomem *omap2_get_clksel(u32 *field_mask, struct clk *clk)
+static void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
 {
-	u32 div_off, mask = ~0;
-	void __iomem *div_addr = 0;
+	if (unlikely((clk->clksel_reg == 0) || (clk->clksel_mask == 0)))
+		return NULL;
 
-	div_off = clk->rate_offset;
+	*field_mask = clk->clksel_mask;
 
-	switch (clk->flags & SRC_RATE_SEL_MASK) {
-	case CM_MPU_SEL1:
-		div_addr = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL);
-		mask = OMAP24XX_CLKSEL_MPU_MASK;
-		break;
-	case CM_DSP_SEL1:
-		div_addr = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL);
-		if (cpu_is_omap2420()) {
-			if (div_off == OMAP24XX_CLKSEL_DSP_SHIFT)
-				mask = OMAP24XX_CLKSEL_DSP_MASK;
-			else if (div_off == OMAP2420_CLKSEL_IVA_SHIFT)
-				mask = OMAP2420_CLKSEL_IVA_MASK;
-			else if (div_off == OMAP24XX_CLKSEL_DSP_IF_SHIFT)
-				mask = OMAP24XX_CLKSEL_DSP_IF_MASK;
-		} else if (cpu_is_omap2430()) {
-			if (div_off == OMAP24XX_CLKSEL_DSP_SHIFT)
-				mask = OMAP24XX_CLKSEL_DSP_MASK;
-			else if (div_off == OMAP24XX_CLKSEL_DSP_IF_SHIFT)
-				mask = OMAP24XX_CLKSEL_DSP_IF_MASK;
-		}
-	case CM_GFX_SEL1:
-		div_addr = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL);
-		if (div_off == OMAP_CLKSEL_GFX_SHIFT)
-			mask = OMAP_CLKSEL_GFX_MASK;
-		break;
-	case CM_MODEM_SEL1:
-		div_addr = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL);
-		if (div_off == OMAP2430_CLKSEL_MDM_SHIFT)
-			mask = OMAP2430_CLKSEL_MDM_MASK;
-		break;
-	case CM_SYSCLKOUT_SEL1:
-		div_addr = OMAP24XX_PRCM_CLKOUT_CTRL;
-		if (div_off == OMAP24XX_CLKOUT_DIV_SHIFT)
-			mask = OMAP24XX_CLKOUT_DIV_MASK;
-		else if (div_off == OMAP2420_CLKOUT2_DIV_SHIFT)
-			mask = OMAP2420_CLKOUT2_DIV_MASK;
-		break;
-	case CM_CORE_SEL1:
-		div_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1);
-		switch (div_off) {
-		case OMAP24XX_CLKSEL_L3_SHIFT:
-			mask = OMAP24XX_CLKSEL_L3_MASK;
-			break;
-		case OMAP24XX_CLKSEL_L4_SHIFT:
-			mask = OMAP24XX_CLKSEL_L4_MASK;
-			break;
-		case OMAP24XX_CLKSEL_DSS1_SHIFT:
-			mask = OMAP24XX_CLKSEL_DSS1_MASK;
-			break;
-		case OMAP24XX_CLKSEL_DSS2_SHIFT:
-			mask = OMAP24XX_CLKSEL_DSS2_MASK;
-			break;
-		case OMAP2420_CLKSEL_VLYNQ_SHIFT:
-			mask = OMAP2420_CLKSEL_VLYNQ_MASK;
-			break;
-		case OMAP24XX_CLKSEL_SSI_SHIFT:
-			mask = OMAP24XX_CLKSEL_SSI_MASK;
-			break;
-		case OMAP24XX_CLKSEL_USB_SHIFT:
-			mask = OMAP24XX_CLKSEL_USB_MASK;
-			break;
-		}
-	}
-
-	if (unlikely((mask == ~0) || (div_addr == 0)))
-		return 0;
-
-	*field_mask = mask;
-
-	return div_addr;
+	return clk->clksel_reg;
 }
 
-
 /**
  * omap2_clksel_get_divisor - get current divider applied to parent clock.
  * @clk: OMAP struct clk to use.
@@ -881,7 +815,7 @@ static u32 omap2_clksel_get_divisor(stru
 	u32 field_mask, field_val;
 	void __iomem *div_addr;
 
-	div_addr = omap2_get_clksel(&field_mask, clk);
+	div_addr = omap2_get_clksel(clk, &field_mask);
 	if (div_addr == 0)
 		return 0;
 
@@ -910,7 +844,7 @@ static int omap2_clk_set_rate(struct clk
 		if (validrate != rate)
 			return ret;
 
-		div_addr = omap2_get_clksel(&field_mask, clk);
+		div_addr = omap2_get_clksel(clk, &field_mask);
 		if (div_addr == 0)
 			return ret;
 

-- 

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

* [PATCH 11/28] omap2 clock: convert omap2_clksel_get_src_field() to use new clksel struct
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (8 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 10/28] omap2 clock: convert omap2_get_clksel " Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:53 ` [PATCH 12/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_rate() Paul Walmsley
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_get_src_field.patch --]
[-- Type: text/plain, Size: 7524 bytes --]

Convert omap2_clksel_get_src_field() to use new struct clksel and struct
clksel_rate data. 

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

---
 arch/arm/mach-omap2/clock.c |  206 +++++---------------------------------------
 1 file changed, 25 insertions(+), 181 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -46,38 +46,11 @@
 #define EN_APLL_STOPPED			0
 #define EN_APLL_LOCKED			3
 
-/* CM_{CLKSEL2_CORE,CLKSEL_WKUP}.CLKSEL_GPT* options (24XX) */
-#define CLKSEL_GPT_32K			0
-#define CLKSEL_GPT_SYSCLK		1
-#define CLKSEL_GPT_EXTALTCLK		2
-
-/* CM_CLKSEL1_CORE.CLKSEL_DSS1 options (24XX) */
-#define CLKSEL_DSS1_SYSCLK		0
-#define CLKSEL_DSS1_CORECLK_16		0x10
-
-/* CM_CLKSEL1_CORE.CLKSEL_DSS2 options (24XX) */
-#define CLKSEL_DSS2_SYSCLK		0
-#define CLKSEL_DSS2_48MHZ		1
-
 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
 #define APLLS_CLKIN_19_2MHZ		0
 #define APLLS_CLKIN_13MHZ		2
 #define APLLS_CLKIN_12MHZ		3
 
-/* CM_CLKSEL1_PLL.54M_SOURCE options (24XX) */
-#define CLK_54M_SOURCE_APLL		0
-#define CLK_54M_SOURCE_EXTALTCLK	1
-
-/* CM_CLKSEL1_PLL.48M_SOURCE options (24XX) */
-#define CLK_48M_SOURCE_APLL		0
-#define CLK_48M_SOURCE_EXTALTCLK	1
-
-/* PRCM_CLKOUT_CTRL.CLKOUT_SOURCE options (2420) */
-#define CLKOUT_SOURCE_CORE_CLK		0
-#define CLKOUT_SOURCE_SYS_CLK		1
-#define CLKOUT_SOURCE_96M_CLK		2
-#define CLKOUT_SOURCE_54M_CLK		3
-
 #define MAX_PLL_LOCK_WAIT		100000
 
 //#define DOWN_VARIABLE_DPLL 1			/* Experimental */
@@ -473,28 +446,6 @@ static void omap2_clksel_recalc(struct c
 		propagate_rate(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.
- */
-static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
-					   u32 src_rate, u32 tgt_rate)
-{
-	int i, test_rate;
-
-	if (div_array == NULL)
-		return ~1;
-
-	for (i = 0; i < size; i++) {
-		test_rate = src_rate / *div_array;
-		if (test_rate <= tgt_rate)
-			return *div_array;
-		++div_array;
-	}
-
-	return ~0;	/* No acceptable divider */
-}
-
 /**
  * omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
  * @clk: OMAP struct clk ptr to inspect
@@ -875,151 +826,44 @@ static int omap2_clk_set_rate(struct clk
 	return ret;
 }
 
-/* Converts encoded control register address into a full address */
+/*
+ * Converts encoded control register address into a full address
+ * On error, *src_addr will be returned as 0.
+ */
 static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
 				      struct clk *src_clk, u32 *field_mask,
 				      struct clk *clk, u32 *parent_div)
 {
-	u32 val = ~0, mask = 0;
-	void __iomem *src_reg_addr = 0;
-	u32 reg_offset;
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
 
 	*parent_div = 0;
-	reg_offset = clk->src_offset;
+	*src_addr = 0;
 
-	/* Find target control register.*/
-	switch (clk->flags & SRC_RATE_SEL_MASK) {
-	case CM_CORE_SEL1:
-		src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1);
-		if (reg_offset == OMAP24XX_CLKSEL_DSS2_SHIFT) {
-			mask = OMAP24XX_CLKSEL_DSS2_MASK;
-			if (src_clk == &sys_ck)
-				val = CLKSEL_DSS2_SYSCLK;
-			else if (src_clk == &func_48m_ck)
-				val = CLKSEL_DSS2_48MHZ;
-			else
-				WARN_ON(1); /* unknown src_clk */
-		} else if (reg_offset == OMAP24XX_CLKSEL_DSS1_SHIFT) {
-			mask = OMAP24XX_CLKSEL_DSS1_MASK;
-			if (src_clk == &sys_ck) {
-				val = CLKSEL_DSS1_SYSCLK;
-			} else if (src_clk == &core_ck) {
-				val = CLKSEL_DSS1_CORECLK_16;
-				*parent_div = 16;
-			} else {
-				WARN_ON(1); /* unknown src clk */
-			}
-		} else if ((reg_offset == OMAP2420_CLKSEL_VLYNQ_SHIFT) &&
-			   cpu_is_omap2420()) {
-			mask = OMAP2420_CLKSEL_VLYNQ_MASK;
-			if (src_clk == &func_96m_ck) {
-				val = CLKSEL_VLYNQ_96MHZ;
-			} else if (src_clk == &core_ck) {
-				val = CLKSEL_VLYNQ_CORECLK_16;
-				*parent_div = 16;
-			} else {
-				WARN_ON(1); /* unknown src_clk */
-			}
-		} else {
-			WARN_ON(1); /* unknown reg_offset */
-		}
-		break;
-	case CM_CORE_SEL2:
-		WARN_ON(reg_offset < OMAP24XX_CLKSEL_GPT2_SHIFT ||
-			reg_offset > OMAP24XX_CLKSEL_GPT12_SHIFT);
-		src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2);
-		mask = OMAP24XX_CLKSEL_GPT2_MASK;
-		mask <<= (reg_offset - OMAP24XX_CLKSEL_GPT2_SHIFT);
-		if (src_clk == &func_32k_ck)
-			val = CLKSEL_GPT_32K;
-		else if (src_clk == &sys_ck)
-			val = CLKSEL_GPT_SYSCLK;
-		else if (src_clk == &alt_ck)
-			val = CLKSEL_GPT_EXTALTCLK;
-		else
-			WARN_ON(1);  /* unknown src_clk */
-		break;
-	case CM_WKUP_SEL1:
-		WARN_ON(reg_offset != 0); /* unknown reg_offset */
-		src_reg_addr = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL);
-		mask = OMAP24XX_CLKSEL_GPT1_MASK;
-		if (src_clk == &func_32k_ck)
-			val = CLKSEL_GPT_32K;
-		else if (src_clk == &sys_ck)
-			val = CLKSEL_GPT_SYSCLK;
-		else if (src_clk == &alt_ck)
-			val = CLKSEL_GPT_EXTALTCLK;
-		else
-			WARN_ON(1); /* unknown src_clk */
-		break;
-	case CM_PLL_SEL1:
-		src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1);
-		if (reg_offset == 0x3) {
-			mask = OMAP24XX_48M_SOURCE;
-			if (src_clk == &apll96_ck)
-				val = CLK_48M_SOURCE_APLL;
-			else if (src_clk == &alt_ck)
-				val = CLK_48M_SOURCE_EXTALTCLK;
-			else
-				WARN_ON(1); /* unknown src_clk */
-		}
-		else if (reg_offset == 0x5) {
-			mask = OMAP24XX_54M_SOURCE;
-			if (src_clk == &apll54_ck)
-				val = CLK_54M_SOURCE_APLL;
-			else if (src_clk == &alt_ck)
-				val = CLK_54M_SOURCE_EXTALTCLK;
-			else
-				WARN_ON(1); /* unknown src_clk */
-		} else {
-			WARN_ON(1); /* unknown reg_offset */
-		}
-		break;
-	case CM_PLL_SEL2:
-		WARN_ON(reg_offset != 0);
-		src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2);
-		mask = OMAP24XX_CORE_CLK_SRC_MASK;
-		if (src_clk == &func_32k_ck)
-			val = CORE_CLK_SRC_32K;
-		else if (src_clk == &dpll_ck)
-			val = CORE_CLK_SRC_DPLL_X2;
-		else
-			WARN_ON(1); /* unknown src_clk */
-		break;
-	case CM_SYSCLKOUT_SEL1:
-		src_reg_addr = OMAP24XX_PRCM_CLKOUT_CTRL;
-
-		if (reg_offset == OMAP24XX_CLKOUT_SOURCE_SHIFT) {
-			mask = OMAP24XX_CLKOUT_SOURCE_MASK;
-		} else if (reg_offset == OMAP2420_CLKOUT2_SOURCE_SHIFT) {
-			mask = OMAP2420_CLKOUT2_SOURCE_MASK;
-		} else {
-			WARN_ON(1); /* unknown reg_offset */
-		}
+	clks = omap2_get_clksel_by_parent(clk, src_clk);
+	if (clks == NULL)
+		return 0;
 
-		if (src_clk == &dpll_ck)
-			val = 0;
-		else if (src_clk == &sys_ck)
-			val = 1;
-		else if (src_clk == &func_96m_ck)
-			val = 2;
-		else if (src_clk == &func_54m_ck)
-			val = 3;
-		else
-			WARN_ON(1); /* unknown src_clk */
-		break;
+	for (clkr = clks->rates; clkr->div; clkr++) {
+		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
+			break; /* Found the default rate for this platform */
 	}
 
-	if (val == ~0)			/* Catch errors in offset */
-		*src_addr = 0;
-	else
-		*src_addr = src_reg_addr;
+	if (!clkr->div) {
+		printk(KERN_ERR "clock: Could not find default rate for "
+		       "clock %s parent %s\n", clk->name,
+		       src_clk->parent->name);
+		return 0;
+	}
 
-	WARN_ON(mask == 0);
+	/* Should never happen.  Add a clksel mask to the struct clk. */
+	WARN_ON(clk->clksel_mask == 0);
 
-	*field_mask = mask;
+	*field_mask = clk->clksel_mask;
+	*src_addr = clk->clksel_reg;
+	*parent_div = clkr->div;
 
-	return val;
+	return clkr->val;
 }
 
 static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)

-- 

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

* [PATCH 12/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_rate()
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (9 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 11/28] omap2 clock: convert omap2_clksel_get_src_field() " Paul Walmsley
@ 2007-08-20  9:53 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 13/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_parent() Paul Walmsley
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:53 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_set_rate.patch --]
[-- Type: text/plain, Size: 1472 bytes --]

Stop using clk->rate_offset in omap2_clk_set_rate(); use what we get
from the clksel code instead.

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

---
 arch/arm/mach-omap2/clock.c |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -780,17 +780,14 @@ static u32 omap2_clksel_get_divisor(stru
 static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	int ret = -EINVAL;
-	u32 div_off, field_mask, field_val, reg_val, validrate;
-	u32 new_div = 0;
+	u32 field_mask, field_val, reg_val, new_div = 0;
+	unsigned long validrate;
 	void __iomem *div_addr;
 
 	if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
 		if (clk == &dpll_ck)
 			return omap2_reprogram_dpll(clk, rate);
 
-		/* Isolate control register */
-		div_off = clk->rate_offset;
-
 		validrate = omap2_clksel_round_rate(clk, rate, &new_div);
 		if (validrate != rate)
 			return ret;
@@ -805,7 +802,7 @@ static int omap2_clk_set_rate(struct clk
 
 		reg_val = cm_read_reg(div_addr);
 		reg_val &= ~field_mask;
-		reg_val |= (field_val << div_off);
+		reg_val |= (field_val << convert_mask_to_shift(field_mask));
 		cm_write_reg(reg_val, div_addr);
 		wmb();
 		clk->rate = clk->parent->rate / new_div;

-- 

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

* [PATCH 13/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_parent()
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (10 preceding siblings ...)
  2007-08-20  9:53 ` [PATCH 12/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_rate() Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 14/28] omap2 clock: clean out old code from omap2_clksel_recalc() Paul Walmsley
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_set_parent.patch --]
[-- Type: text/plain, Size: 1125 bytes --]

Stop using clk->src_offset in omap2_clk_set_parent(); use what we get
from the clksel code instead.

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

---
 arch/arm/mach-omap2/clock.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -884,7 +884,7 @@ static int omap2_clk_set_parent(struct c
 
 	/* Set new source value (previous dividers if any in effect) */
 	reg_val = __raw_readl(src_addr) & ~field_mask;
-	reg_val |= (field_val << clk->src_offset);
+	reg_val |= (field_val << convert_mask_to_shift(field_mask));
 	__raw_writel(reg_val, src_addr);
 	wmb();
 
@@ -905,6 +905,9 @@ static int omap2_clk_set_parent(struct c
 	if (parent_div > 0)
 		clk->rate /= parent_div;
 
+	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
+		 clk->name, clk->parent->name, clk->rate);
+
 	if (unlikely(clk->flags & RATE_PROPAGATES))
 		propagate_rate(clk);
 

-- 

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

* [PATCH 14/28] omap2 clock: clean out old code from omap2_clksel_recalc()
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (11 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 13/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_parent() Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 15/28] omap2 clock: convert remaining clksel clocks to use omap2_clksel_recalc Paul Walmsley
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: convert_clksel_recalc.patch --]
[-- Type: text/plain, Size: 1969 bytes --]

Get rid of now-obsolete code in omap2_clksel_recalc().

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

---
 arch/arm/mach-omap2/clock.c |   24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -8,6 +8,10 @@
  *  Cleaned up and modified to use omap shared clock framework by
  *  Tony Lindgren <tony@atomide.com>
  *
+ *  Copyright (C) 2007 Texas Instruments, Inc.
+ *  Copyright (C) 2007 Nokia Corporation
+ *  Paul Walmsley
+ *
  *  Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
@@ -38,10 +42,6 @@
 
 #undef DEBUG
 
-/* CM_CLKSEL1_CORE.CLKSEL_VLYNQ options (2420) */
-#define CLKSEL_VLYNQ_96MHZ		0
-#define CLKSEL_VLYNQ_CORECLK_16		0x10
-
 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
 #define EN_APLL_STOPPED			0
 #define EN_APLL_LOCKED			3
@@ -420,19 +420,9 @@ static void omap2_dpll_recalc(struct clk
  */
 static void omap2_clksel_recalc(struct clk * clk)
 {
-	u32 clksel1_core, div = 0;
+	u32 div = 0;
 
-	clksel1_core = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1);
-
-	if ((clk == &dss1_fck) &&
-	    (clksel1_core & OMAP24XX_CLKSEL_DSS1_MASK) == 0) {
-		div = 1;
-	}
-
-	if ((clk == &vlynq_fck) && cpu_is_omap2420() &&
-	    (clksel1_core & OMAP2420_CLKSEL_VLYNQ_MASK) == CLKSEL_VLYNQ_96MHZ) {
-		div = 1;
-	}
+	pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
 
 	div = omap2_clksel_get_divisor(clk);
 	if (div == 0)
@@ -442,6 +432,8 @@ static void omap2_clksel_recalc(struct c
 		return;
 	clk->rate = clk->parent->rate / div;
 
+	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+
 	if (unlikely(clk->flags & RATE_PROPAGATES))
 		propagate_rate(clk);
 }

-- 

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

* [PATCH 15/28] omap2 clock: convert remaining clksel clocks to use omap2_clksel_recalc
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (12 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 14/28] omap2 clock: clean out old code from omap2_clksel_recalc() Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 16/28] omap2 clock: remove all {src, rate}_offset fields from struct clk Paul Walmsley
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: use_clksel_recalc_for_all_clksel_clks.patch --]
[-- Type: text/plain, Size: 8344 bytes --]

This completes the transition to struct clksel/clksel_rate by converting the
remaining clksel clocks to call omap2_clksel_recalc() on rate recalculation.
Also remove RATE_FIXED from some clocks that can now recalculate their own
rates correctly via clksel.

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

---
 arch/arm/mach-omap2/clock.h |   56 +++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 29 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.h
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/mach-omap24xx/clock.h
+ *  linux/arch/arm/mach-omap2/clock.h
  *
  *  Copyright (C) 2005 Texas Instruments Inc.
  *  Richard Woodruff <r-woodruff2@ti.com>
@@ -9,6 +9,10 @@
  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
  *
+ *  Copyright (C) 2007 Texas Instruments, Inc.
+ *  Copyright (C) 2007 Nokia Corporation
+ *  Revised by Paul Walmsley
+ *
  * 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.
@@ -687,16 +691,15 @@ static const struct clksel func_54m_clks
 static struct clk func_54m_ck = {
 	.name		= "func_54m_ck",
 	.parent		= &apll54_ck,	/* can also be alt_clk */
-	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
+				CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_54M_SOURCE_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_54M_SOURCE,
 	.clksel		= func_54m_clksel,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk core_ck = {
@@ -728,15 +731,13 @@ static const struct clksel func_96m_clks
 static struct clk func_96m_ck = {
 	.name		= "func_96m_ck",
 	.parent		= &apll96_ck,
-	.rate		= 96000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP2430_96M_SOURCE,
 	.clksel		= func_96m_clksel,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /* func_48m_ck */
@@ -760,16 +761,15 @@ static const struct clksel func_48m_clks
 static struct clk func_48m_ck = {
 	.name		= "func_48m_ck",
 	.parent		= &apll96_ck,	 /* 96M or Alt */
-	.rate		= 48000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES |
+				CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
 	.src_offset	= OMAP24XX_48M_SOURCE_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_48M_SOURCE,
 	.clksel		= func_48m_clksel,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk func_12m_ck = {
@@ -828,7 +828,6 @@ static const struct clksel common_clkout
 static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
-	.rate		= 54000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
 				RATE_PROPAGATES,
@@ -839,7 +838,7 @@ static struct clk sys_clkout_src = {
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
 	.clksel		= common_clkout_src_clksel,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static const struct clksel_rate common_clkout_rates[] = {
@@ -882,7 +881,7 @@ static struct clk sys_clkout2_src = {
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
 	.clksel		= common_clkout_src_clksel,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static const struct clksel sys_clkout2_clksel[] = {
@@ -900,7 +899,7 @@ static struct clk sys_clkout2 = {
 	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
 	.clksel		= sys_clkout2_clksel,
 	.rate_offset	= OMAP2420_CLKOUT2_DIV_SHIFT,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk emul_ck = {
@@ -1466,8 +1465,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.name		= "dss2_fck",
 	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_CORE_SEL1 | RATE_FIXED |
-				DELAYED_APP,
+				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
 	.src_offset	= OMAP24XX_CLKSEL_DSS2_SHIFT,
@@ -1536,7 +1534,7 @@ static struct clk gpt1_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt2_ick = {
@@ -1560,7 +1558,7 @@ static struct clk gpt2_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt3_ick = {
@@ -1584,7 +1582,7 @@ static struct clk gpt3_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt4_ick = {
@@ -1608,7 +1606,7 @@ static struct clk gpt4_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt5_ick = {
@@ -1632,7 +1630,7 @@ static struct clk gpt5_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt6_ick = {
@@ -1656,7 +1654,7 @@ static struct clk gpt6_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt7_ick = {
@@ -1680,7 +1678,7 @@ static struct clk gpt7_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt8_ick = {
@@ -1704,7 +1702,7 @@ static struct clk gpt8_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt9_ick = {
@@ -1728,7 +1726,7 @@ static struct clk gpt9_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt10_ick = {
@@ -1752,7 +1750,7 @@ static struct clk gpt10_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt11_ick = {
@@ -1776,7 +1774,7 @@ static struct clk gpt11_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt12_ick = {
@@ -1800,7 +1798,7 @@ static struct clk gpt12_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
 	.clksel		= gpt_clksel,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp1_ick = {

-- 

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

* [PATCH 16/28] omap2 clock: remove all {src, rate}_offset fields from struct clk
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (13 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 15/28] omap2 clock: convert remaining clksel clocks to use omap2_clksel_recalc Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 17/28] omap2 clock: use the struct clk round_rate field for clksel rate rounding code Paul Walmsley
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: nuke_src_and_rate_offset.patch --]
[-- Type: text/plain, Size: 14941 bytes --]

src_offset and rate_offset are no longer used in OMAP2 clock framework
after the struct clksel/struct clksel_rate additions.  Remove these
fields from clock.h and #ifdef out those fields for OMAP24XX compiles.

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

---
 arch/arm/mach-omap2/clock.c       |    4 ++--
 arch/arm/mach-omap2/clock.h       |   38 +-------------------------------------
 include/asm-arm/arch-omap/clock.h |    5 +++--
 3 files changed, 6 insertions(+), 41 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -121,7 +121,7 @@ static void omap2_sys_clk_recalc(struct 
 		div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
 		/* Test if ext clk divided by 1 or 2 */
 		div &= OMAP_SYSCLKDIV_MASK;
-		div >>= clk->rate_offset;
+		div >>= OMAP_SYSCLKDIV_SHIFT;
 		clk->rate = (clk->parent->rate / div);
 	}
 	propagate_rate(clk);
@@ -1032,7 +1032,7 @@ static void __init omap2_get_crystal_rat
 
 	div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
 	div &= OMAP_SYSCLKDIV_MASK;
-	div >>= sys->rate_offset;
+	div >>= OMAP_SYSCLKDIV_SHIFT;
 
 	osc->rate = sclk * div;
 	sys->rate = sclk;
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -11,7 +11,7 @@
  *
  *  Copyright (C) 2007 Texas Instruments, Inc.
  *  Copyright (C) 2007 Nokia Corporation
- *  Revised by Paul Walmsley
+ *  Paul Walmsley
  *
  * 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
@@ -615,7 +615,6 @@ static struct clk sys_ck = {		/* (*12, *
 	.rate		= 13000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
-	.rate_offset	= OMAP_SYSCLKDIV_SHIFT, /* sysclkdiv 1 or 2, already handled or no boot */
 	.recalc		= &omap2_sys_clk_recalc,
 };
 
@@ -694,7 +693,6 @@ static struct clk func_54m_ck = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
-	.src_offset	= OMAP24XX_54M_SOURCE_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_54M_SOURCE,
@@ -764,7 +762,6 @@ static struct clk func_48m_ck = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				CM_PLL_SEL1 | RATE_PROPAGATES |
 				PARENT_CONTROLS_CLOCK,
-	.src_offset	= OMAP24XX_48M_SOURCE_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_48M_SOURCE,
@@ -831,7 +828,6 @@ static struct clk sys_clkout_src = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
 				RATE_PROPAGATES,
-	.src_offset	= OMAP24XX_CLKOUT_SOURCE_SHIFT,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -864,7 +860,6 @@ static struct clk sys_clkout = {
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
 	.clksel		= sys_clkout_clksel,
-	.rate_offset	= OMAP24XX_CLKOUT_DIV_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -872,7 +867,6 @@ static struct clk sys_clkout = {
 static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
-	.src_offset	= OMAP2420_CLKOUT2_SOURCE_SHIFT,
 	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
 				RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
@@ -898,7 +892,6 @@ static struct clk sys_clkout2 = {
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
 	.clksel		= sys_clkout2_clksel,
-	.rate_offset	= OMAP2420_CLKOUT2_DIV_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -942,7 +935,6 @@ static struct clk mpu_ck = {	/* Control 
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL |
 				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT | RATE_PROPAGATES,
-	.rate_offset	= OMAP24XX_CLKSEL_MPU_SHIFT,	/* bits 0-4 */
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
@@ -983,7 +975,6 @@ static struct clk iva2_1_fck = {
 	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
 				DELAYED_APP | RATE_PROPAGATES |
 				CONFIG_PARTICIPANT,
-	.rate_offset	= OMAP24XX_CLKSEL_DSP_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1010,7 +1001,6 @@ static struct clk iva2_1_ick = {
 	.parent		= &iva2_1_fck,
 	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
-	.rate_offset	= OMAP24XX_CLKSEL_DSP_IF_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
 	.clksel		= iva2_1_ick_clksel,
@@ -1044,7 +1034,6 @@ static struct clk dsp_fck = {
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
 			DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
-	.rate_offset	= OMAP24XX_CLKSEL_DSP_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1070,7 +1059,6 @@ static struct clk dsp_ick = {
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
-	.rate_offset	= OMAP24XX_CLKSEL_DSP_IF_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,		/* for ipi */
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1100,7 +1088,6 @@ static struct clk iva1_ifck = {
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL |
 			CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
-	.rate_offset	= OMAP2420_CLKSEL_IVA_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1162,7 +1149,6 @@ static struct clk core_l3_ck = {	/* Used
 				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT |
 				RATE_PROPAGATES,
-	.rate_offset	= OMAP24XX_CLKSEL_L3_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
 	.clksel		= core_l3_clksel,
@@ -1190,7 +1176,6 @@ static struct clk usb_l4_ick = {	/* FS-U
 				CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.rate_offset	= OMAP24XX_CLKSEL_USB_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
 	.clksel		= usb_l4_ick_clksel,
@@ -1231,7 +1216,6 @@ static struct clk ssi_ssr_sst_fck = {
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_sst_fck_clksel,
-	.rate_offset	= OMAP24XX_CLKSEL_SSI_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -1272,7 +1256,6 @@ static struct clk gfx_3d_fck = {
 				RATE_CKCTL | CM_GFX_SEL1,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
-	.rate_offset	= OMAP_CLKSEL_GFX_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_fck_clksel,
@@ -1286,7 +1269,6 @@ static struct clk gfx_2d_fck = {
 				RATE_CKCTL | CM_GFX_SEL1,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
-	.rate_offset	= OMAP_CLKSEL_GFX_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_fck_clksel,
@@ -1327,7 +1309,6 @@ static struct clk mdm_ick = {		/* used b
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
-	.rate_offset	= OMAP2430_CLKSEL_MDM_SHIFT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
@@ -1369,7 +1350,6 @@ static struct clk l4_ck = {		/* used bot
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
 				DELAYED_APP | RATE_PROPAGATES,
-	.rate_offset	= OMAP24XX_CLKSEL_L4_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
 	.clksel		= l4_clksel,
@@ -1436,8 +1416,6 @@ static struct clk dss1_fck = {
 				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.rate_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
@@ -1468,7 +1446,6 @@ static struct clk dss2_fck = {		/* Alt c
 				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_DSS2_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
@@ -1529,7 +1506,6 @@ static struct clk gpt1_fck = {
 				CM_WKUP_SEL1,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, OMAP24XX_CM_FCLKEN),	/* Bit0 */
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT1_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
@@ -1553,7 +1529,6 @@ static struct clk gpt2_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT2_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
@@ -1577,7 +1552,6 @@ static struct clk gpt3_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT3_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
@@ -1601,7 +1575,6 @@ static struct clk gpt4_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT4_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
@@ -1625,7 +1598,6 @@ static struct clk gpt5_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT5_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
@@ -1649,7 +1621,6 @@ static struct clk gpt6_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT6_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
@@ -1673,7 +1644,6 @@ static struct clk gpt7_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT7_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
@@ -1697,7 +1667,6 @@ static struct clk gpt8_fck = {
 				CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT8_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
@@ -1721,7 +1690,6 @@ static struct clk gpt9_fck = {
 					CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT9_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
@@ -1745,7 +1713,6 @@ static struct clk gpt10_fck = {
 					CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT10_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
@@ -1769,7 +1736,6 @@ static struct clk gpt11_fck = {
 					CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT11_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
@@ -1793,7 +1759,6 @@ static struct clk gpt12_fck = {
 					CM_CORE_SEL2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.src_offset	= OMAP24XX_CLKSEL_GPT12_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
@@ -2327,7 +2292,6 @@ static struct clk vlynq_fck = {
 	.flags		= CLOCK_IN_OMAP242X  | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
-	.src_offset	= OMAP2420_CLKSEL_VLYNQ_SHIFT,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -41,8 +41,6 @@ struct clk {
 	__u32			flags;
 	void __iomem		*enable_reg;
 	__u8			enable_bit;
-	__u8			rate_offset;
-	__u8			src_offset;
 	__s8			usecount;
 	void			(*recalc)(struct clk *);
 	int			(*set_rate)(struct clk *, unsigned long);
@@ -55,6 +53,9 @@ struct clk {
 	void __iomem		*clksel_reg;
 	u32			clksel_mask;
 	const struct clksel	*clksel;
+#else
+	__u8			rate_offset;
+	__u8			src_offset;
 #endif
 };
 

-- 

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

* [PATCH 17/28] omap2 clock: use the struct clk round_rate field for clksel rate rounding code
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (14 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 16/28] omap2 clock: remove all {src, rate}_offset fields from struct clk Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 19/28] omap2 clock: drop RATE_CKCTL from all OMAP2 clocks Paul Walmsley
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: split_round_rate.patch --]
[-- Type: text/plain, Size: 8840 bytes --]

The OMAP clock framework struct clk contains a field, .round_rate,
that is intended to contain a function pointer to rate rounding code.
Take advantage of it by converting all clksel clocks' round_rate field
to point to omap2_clksel_round_rate().  Rename the existing
omap2_clksel_round_rate() to omap2_clksel_round_rate_div(), to signify
that it returns divisor information as well, and set up
omap2_clksel_round_rate() as a wrapper for the clock framework to use.
Simplify omap2_clk_round_rate() accordingly.

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

---
 arch/arm/mach-omap2/clock.c |   42 ++++++++++++++++++++++++++++++------------
 arch/arm/mach-omap2/clock.h |   21 +++++++++++++++++++++
 2 files changed, 51 insertions(+), 12 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -471,7 +471,7 @@ const static struct clksel *omap2_get_cl
 }
 
 /**
- * omap2_clksel_round_rate - find divisor for the given clock and target rate.
+ * omap2_clksel_round_rate_div - find divisor for the given clock and rate
  * @clk: OMAP struct clk to use
  * @target_rate: desired clock rate
  * @new_div: ptr to where we should store the divisor
@@ -483,15 +483,16 @@ const static struct clksel *omap2_get_cl
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
-static u32 omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate,
-				   u32 *new_div)
+static u32 omap2_clksel_round_rate_div(struct clk *clk,
+				       unsigned long target_rate,
+				       u32 *new_div)
 {
 	unsigned long test_rate;
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 	u32 last_div = 0;
 
-	printk(KERN_INFO "clock: clksel_round_rate for %s target_rate %ld\n",
+	printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n",
 	       clk->name, target_rate);
 
 	*new_div = 1;
@@ -532,20 +533,37 @@ static u32 omap2_clksel_round_rate(struc
 	return (clk->parent->rate / clkr->div);
 }
 
-/* Given a clock and a rate apply a clock specific rounding function */
-static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
+/**
+ * omap2_clksel_round_rate - find rounded rate for the given clock and rate
+ * @clk: OMAP struct clk to use
+ * @target_rate: desired clock 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.
+ */
+static long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
 {
-	u32 new_div = 0;
+	u32 new_div;
 
-	if (clk->flags & RATE_FIXED)
-		return clk->rate;
+	return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
+}
 
-	if (clk->flags & RATE_CKCTL)
-		return omap2_clksel_round_rate(clk, rate, &new_div);
 
+/* Given a clock and a rate apply a clock specific rounding function */
+static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
+{
 	if (clk->round_rate != 0)
 		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,7 +798,7 @@ static int omap2_clk_set_rate(struct clk
 		if (clk == &dpll_ck)
 			return omap2_reprogram_dpll(clk, rate);
 
-		validrate = omap2_clksel_round_rate(clk, rate, &new_div);
+		validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
 		if (validrate != rate)
 			return ret;
 
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -39,6 +39,8 @@ static u32 omap2_clksel_to_divisor(struc
 static u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
 static void omap2_dpll_recalc(struct clk *clk);
 static void omap2_fixed_divisor_recalc(struct clk *clk);
+static long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
+
 
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
@@ -736,6 +738,7 @@ static struct clk func_96m_ck = {
 	.clksel_mask	= OMAP2430_96M_SOURCE,
 	.clksel		= func_96m_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /* func_48m_ck */
@@ -767,6 +770,7 @@ static struct clk func_48m_ck = {
 	.clksel_mask	= OMAP24XX_48M_SOURCE,
 	.clksel		= func_48m_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk func_12m_ck = {
@@ -861,6 +865,7 @@ static struct clk sys_clkout = {
 	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
 	.clksel		= sys_clkout_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /* In 2430, new in 2420 ES2 */
@@ -940,6 +945,7 @@ static struct clk mpu_ck = {	/* Control 
 	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
 	.clksel		= mpu_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate     = &omap2_clksel_round_rate
 };
 
 /*
@@ -981,6 +987,7 @@ static struct clk iva2_1_fck = {
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
 	.clksel		= iva2_1_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /* iva2_1_ick */
@@ -1005,6 +1012,8 @@ static struct clk iva2_1_ick = {
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
 	.clksel		= iva2_1_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
+
 };
 
 /*
@@ -1040,6 +1049,7 @@ 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
 };
 
 static const struct clksel_rate dsp_ick_core_rates[] = {
@@ -1094,6 +1104,7 @@ static struct clk iva1_ifck = {
 	.clksel_mask	= OMAP2420_CLKSEL_IVA_MASK,
 	.clksel		= iva1_ifck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /* IVA1 mpu/int/i/f clocks are /2 of parent */
@@ -1153,6 +1164,7 @@ static struct clk core_l3_ck = {	/* Used
 	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
 	.clksel		= core_l3_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /* usb_l4_ick */
@@ -1180,6 +1192,7 @@ static struct clk usb_l4_ick = {	/* FS-U
 	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
 	.clksel		= usb_l4_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /*
@@ -1217,6 +1230,7 @@ static struct clk ssi_ssr_sst_fck = {
 	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_sst_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 /*
@@ -1260,6 +1274,7 @@ static struct clk gfx_3d_fck = {
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk gfx_2d_fck = {
@@ -1273,6 +1288,7 @@ static struct clk gfx_2d_fck = {
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk gfx_ick = {
@@ -1315,6 +1331,7 @@ static struct clk mdm_ick = {		/* used b
 	.clksel_mask	= OMAP2430_CLKSEL_MDM_MASK,
 	.clksel		= mdm_ick_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk mdm_osc_ck = {
@@ -1354,6 +1371,7 @@ static struct clk l4_ck = {		/* used bot
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
 	.clksel		= l4_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk ssi_l4_ick = {
@@ -1421,6 +1439,7 @@ static struct clk dss1_fck = {
 	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
 	.clksel		= dss1_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static const struct clksel_rate dss2_fck_sys_rates[] = {
@@ -1511,6 +1530,7 @@ static struct clk gpt1_fck = {
 	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
 	.clksel		= gpt_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk gpt2_ick = {
@@ -2297,6 +2317,7 @@ static struct clk vlynq_fck = {
 	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
 	.clksel		= vlynq_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate
 };
 
 static struct clk sdrc_ick = {

-- 

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

* [PATCH 19/28] omap2 clock: drop RATE_CKCTL from all OMAP2 clocks
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (15 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 17/28] omap2 clock: use the struct clk round_rate field for clksel rate rounding code Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 20/28] omap2 clock: remove *_SEL* clock flags Paul Walmsley
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: nuke_rate_ckctl.patch --]
[-- Type: text/plain, Size: 8839 bytes --]

RATE_CKCTL is no longer meaningful in the OMAP2 clock framework, so, drop it
from all clocks.  We keep the flag around since it's still used by OMAP1.

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

---
 arch/arm/mach-omap2/clock.h |   45 ++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.h
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -641,8 +641,7 @@ static struct clk dpll_ck = {
 	.name		= "dpll_ck",
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | RATE_CKCTL | CM_PLL_SEL1 |
-				ALWAYS_ENABLED,
+				RATE_PROPAGATES | CM_PLL_SEL1 |	ALWAYS_ENABLED,
 	.recalc		= &omap2_dpll_recalc,
 	.set_rate	= &omap2_reprogram_dpll,
 };
@@ -834,8 +833,7 @@ static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
-				RATE_PROPAGATES,
+				CM_SYSCLKOUT_SEL1 | RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -865,8 +863,7 @@ static struct clk sys_clkout = {
 	.name		= "sys_clkout",
 	.parent		= &sys_clkout_src,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
-				PARENT_CONTROLS_CLOCK,
+				CM_SYSCLKOUT_SEL1 | PARENT_CONTROLS_CLOCK,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
 	.clksel		= sys_clkout_clksel,
@@ -879,7 +876,7 @@ static struct clk sys_clkout = {
 static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 |
 				RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
@@ -901,7 +898,7 @@ static const struct clksel sys_clkout2_c
 static struct clk sys_clkout2 = {
 	.name		= "sys_clkout2",
 	.parent		= &sys_clkout2_src,
-	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 | RATE_CKCTL |
+	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 |
 				PARENT_CONTROLS_CLOCK,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
@@ -948,7 +945,7 @@ static const struct clksel mpu_clksel[] 
 static struct clk mpu_ck = {	/* Control cpu */
 	.name		= "mpu_ck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL |
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.init		= &omap2_init_clksel_parent,
@@ -990,7 +987,7 @@ static const struct clksel iva2_1_fck_cl
 static struct clk iva2_1_fck = {
 	.name		= "iva2_1_fck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+	.flags		= CLOCK_IN_OMAP243X | CM_DSP_SEL1 |
 				DELAYED_APP | RATE_PROPAGATES |
 				CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
@@ -1019,7 +1016,7 @@ static const struct clksel iva2_1_ick_cl
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.parent		= &iva2_1_fck,
-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+	.flags		= CLOCK_IN_OMAP243X | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
@@ -1054,7 +1051,7 @@ static const struct clksel dsp_fck_clkse
 static struct clk dsp_fck = {
 	.name		= "dsp_fck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
 			DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
@@ -1081,7 +1078,7 @@ static const struct clksel dsp_ick_clkse
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,		/* for ipi */
@@ -1110,7 +1107,7 @@ static const struct clksel iva1_ifck_clk
 static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL |
+	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
 			CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
@@ -1172,7 +1169,7 @@ static struct clk core_l3_ck = {	/* Used
 	.name		= "core_l3_ck",
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+				ALWAYS_ENABLED | CM_CORE_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT |
 				RATE_PROPAGATES,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1200,7 +1197,7 @@ static struct clk usb_l4_ick = {	/* FS-U
 	.name		= "usb_l4_ick",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
+				CM_CORE_SEL1 | DELAYED_APP |
 				CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
@@ -1240,7 +1237,7 @@ static struct clk ssi_ssr_sst_fck = {
 	.name		= "ssi_fck",
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+				CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),	/* bit 1 */
 	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1285,7 +1282,7 @@ static struct clk gfx_3d_fck = {
 	.name		= "gfx_3d_fck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_GFX_SEL1,
+				CM_GFX_SEL1,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1300,7 +1297,7 @@ static struct clk gfx_2d_fck = {
 	.name		= "gfx_2d_fck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_GFX_SEL1,
+				CM_GFX_SEL1,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1343,7 +1340,7 @@ static const struct clksel mdm_ick_clkse
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 |
+	.flags		= CLOCK_IN_OMAP243X | CM_MODEM_SEL1 |
 				DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
@@ -1386,7 +1383,7 @@ static struct clk l4_ck = {		/* used bot
 	.name		= "l4_ck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+				ALWAYS_ENABLED | CM_CORE_SEL1 |
 				DELAYED_APP | RATE_PROPAGATES,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
@@ -1453,7 +1450,7 @@ static struct clk dss1_fck = {
 	.name		= "dss1_fck",
 	.parent		= &core_ck,		/* Core or sys */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+				CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1485,7 +1482,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.name		= "dss2_fck",
 	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+				CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -2333,7 +2330,7 @@ static const struct clksel vlynq_fck_clk
 static struct clk vlynq_fck = {
 	.name		= "vlynq_fck",
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X  | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | CM_CORE_SEL1 | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
 	.init		= &omap2_init_clksel_parent,

-- 

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

* [PATCH 20/28] omap2 clock: remove *_SEL* clock flags
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (16 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 19/28] omap2 clock: drop RATE_CKCTL from all OMAP2 clocks Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 21/28] omap2 clock: call clock-specific enable/disable functions if present Paul Walmsley
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: nuke_src_rate_mask.patch --]
[-- Type: text/plain, Size: 17366 bytes --]

We no longer need the *_SEL* clock flags with the struct clksel conversion,
so we get rid of them.  This frees up 10 clock flag bits.

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

---
 arch/arm/mach-omap2/clock.c       |    4 -
 arch/arm/mach-omap2/clock.h       |  111 +++++++++++++-------------------------
 include/asm-arm/arch-omap/clock.h |   11 ---
 3 files changed, 41 insertions(+), 85 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -890,7 +890,7 @@ static int omap2_clk_set_parent(struct c
 	if (unlikely(clk->flags & CONFIG_PARTICIPANT))
 		return -EINVAL;
 
-	if (unlikely(!(clk->flags & SRC_SEL_MASK)))
+	if (!clk->clksel)
 		return -EINVAL;
 
 	field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
@@ -918,7 +918,7 @@ static int omap2_clk_set_parent(struct c
 
 	clk->parent = new_parent;
 
-	/* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
+	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
 	clk->rate = new_parent->rate;
 
 	if (parent_div > 0)
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -62,16 +62,6 @@ struct prcm_config {
 	unsigned char flags;
 };
 
-/* REVISIT: CM_PLL_SEL2 unused */
-
-/* Mask for clksel which support parent settign in set_rate */
-#define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \
-			CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1)
-
-/* Mask for clksel regs which support rate operations */
-#define SRC_RATE_SEL_MASK (SRC_SEL_MASK | CM_MPU_SEL1 | CM_DSP_SEL1 | \
-			CM_GFX_SEL1 | CM_MODEM_SEL1)
-
 /*
  * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
  * These configurations are characterized by voltage and speed for clocks.
@@ -641,7 +631,7 @@ static struct clk dpll_ck = {
 	.name		= "dpll_ck",
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | CM_PLL_SEL1 |	ALWAYS_ENABLED,
+				RATE_PROPAGATES | ALWAYS_ENABLED,
 	.recalc		= &omap2_dpll_recalc,
 	.set_rate	= &omap2_reprogram_dpll,
 };
@@ -694,8 +684,7 @@ static struct clk func_54m_ck = {
 	.name		= "func_54m_ck",
 	.parent		= &apll54_ck,	/* can also be alt_clk */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_PLL_SEL1 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_54M_SOURCE,
@@ -765,8 +754,7 @@ static struct clk func_48m_ck = {
 	.name		= "func_48m_ck",
 	.parent		= &apll96_ck,	 /* 96M or Alt */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_PLL_SEL1 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_48M_SOURCE,
@@ -833,7 +821,7 @@ static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
 	.parent		= &func_54m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_SYSCLKOUT_SEL1 | RATE_PROPAGATES,
+				RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -863,7 +851,7 @@ static struct clk sys_clkout = {
 	.name		= "sys_clkout",
 	.parent		= &sys_clkout_src,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_SYSCLKOUT_SEL1 | PARENT_CONTROLS_CLOCK,
+				PARENT_CONTROLS_CLOCK,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
 	.clksel		= sys_clkout_clksel,
@@ -876,8 +864,7 @@ static struct clk sys_clkout = {
 static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 |
-				RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | RATE_PROPAGATES,
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -898,8 +885,7 @@ static const struct clksel sys_clkout2_c
 static struct clk sys_clkout2 = {
 	.name		= "sys_clkout2",
 	.parent		= &sys_clkout2_src,
-	.flags		= CLOCK_IN_OMAP242X | CM_SYSCLKOUT_SEL1 |
-				PARENT_CONTROLS_CLOCK,
+	.flags		= CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK,
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
 	.clksel		= sys_clkout2_clksel,
@@ -946,7 +932,7 @@ static struct clk mpu_ck = {	/* Control 
 	.name		= "mpu_ck",
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
+				ALWAYS_ENABLED | DELAYED_APP |
 				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
@@ -987,8 +973,7 @@ static const struct clksel iva2_1_fck_cl
 static struct clk iva2_1_fck = {
 	.name		= "iva2_1_fck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP243X | CM_DSP_SEL1 |
-				DELAYED_APP | RATE_PROPAGATES |
+	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | RATE_PROPAGATES |
 				CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
@@ -1016,8 +1001,7 @@ static const struct clksel iva2_1_ick_cl
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.parent		= &iva2_1_fck,
-	.flags		= CLOCK_IN_OMAP243X | CM_DSP_SEL1 |
-				DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
 	.clksel		= iva2_1_ick_clksel,
@@ -1051,8 +1035,8 @@ static const struct clksel dsp_fck_clkse
 static struct clk dsp_fck = {
 	.name		= "dsp_fck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
-			DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP |
+				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1078,8 +1062,7 @@ static const struct clksel dsp_ick_clkse
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
-				DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,		/* for ipi */
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1107,8 +1090,8 @@ static const struct clksel iva1_ifck_clk
 static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 |
-			CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
+				RATE_PROPAGATES | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1169,9 +1152,8 @@ static struct clk core_l3_ck = {	/* Used
 	.name		= "core_l3_ck",
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | CM_CORE_SEL1 |
-				DELAYED_APP | CONFIG_PARTICIPANT |
-				RATE_PROPAGATES,
+				ALWAYS_ENABLED | DELAYED_APP |
+				CONFIG_PARTICIPANT | RATE_PROPAGATES,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
 	.clksel		= core_l3_clksel,
@@ -1197,8 +1179,7 @@ static struct clk usb_l4_ick = {	/* FS-U
 	.name		= "usb_l4_ick",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL1 | DELAYED_APP |
-				CONFIG_PARTICIPANT,
+				DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1237,7 +1218,7 @@ static struct clk ssi_ssr_sst_fck = {
 	.name		= "ssi_fck",
 	.parent		= &core_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL1 | DELAYED_APP,
+				DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),	/* bit 1 */
 	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1281,8 +1262,7 @@ static const struct clksel gfx_fck_clkse
 static struct clk gfx_3d_fck = {
 	.name		= "gfx_3d_fck",
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_GFX_SEL1,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1296,8 +1276,7 @@ static struct clk gfx_3d_fck = {
 static struct clk gfx_2d_fck = {
 	.name		= "gfx_2d_fck",
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_GFX_SEL1,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, OMAP24XX_CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1340,8 +1319,7 @@ static const struct clksel mdm_ick_clkse
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP243X | CM_MODEM_SEL1 |
-				DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
@@ -1383,8 +1361,7 @@ static struct clk l4_ck = {		/* used bot
 	.name		= "l4_ck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | CM_CORE_SEL1 |
-				DELAYED_APP | RATE_PROPAGATES,
+				ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
 	.clksel		= l4_clksel,
@@ -1450,7 +1427,7 @@ static struct clk dss1_fck = {
 	.name		= "dss1_fck",
 	.parent		= &core_ck,		/* Core or sys */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL1 | DELAYED_APP,
+				DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1482,7 +1459,7 @@ static struct clk dss2_fck = {		/* Alt c
 	.name		= "dss2_fck",
 	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL1 | DELAYED_APP,
+				DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1541,8 +1518,7 @@ static struct clk gpt1_ick = {
 static struct clk gpt1_fck = {
 	.name		= "gpt1_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_WKUP_SEL1,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, OMAP24XX_CM_FCLKEN),	/* Bit0 */
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1566,8 +1542,7 @@ static struct clk gpt2_ick = {
 static struct clk gpt2_fck = {
 	.name		= "gpt2_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1589,8 +1564,7 @@ static struct clk gpt3_ick = {
 static struct clk gpt3_fck = {
 	.name		= "gpt3_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1612,8 +1586,7 @@ static struct clk gpt4_ick = {
 static struct clk gpt4_fck = {
 	.name		= "gpt4_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1635,8 +1608,7 @@ static struct clk gpt5_ick = {
 static struct clk gpt5_fck = {
 	.name		= "gpt5_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1658,8 +1630,7 @@ static struct clk gpt6_ick = {
 static struct clk gpt6_fck = {
 	.name		= "gpt6_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1681,8 +1652,7 @@ static struct clk gpt7_ick = {
 static struct clk gpt7_fck = {
 	.name		= "gpt7_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1704,8 +1674,7 @@ static struct clk gpt8_ick = {
 static struct clk gpt8_fck = {
 	.name		= "gpt8_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1727,8 +1696,7 @@ static struct clk gpt9_ick = {
 static struct clk gpt9_fck = {
 	.name		= "gpt9_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-					CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1750,8 +1718,7 @@ static struct clk gpt10_ick = {
 static struct clk gpt10_fck = {
 	.name		= "gpt10_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-					CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1773,8 +1740,7 @@ static struct clk gpt11_ick = {
 static struct clk gpt11_fck = {
 	.name		= "gpt11_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-					CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -1796,8 +1762,7 @@ static struct clk gpt12_ick = {
 static struct clk gpt12_fck = {
 	.name		= "gpt12_fck",
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-					CM_CORE_SEL2,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
 	.init		= &omap2_init_clksel_parent,
@@ -2330,7 +2295,7 @@ static const struct clksel vlynq_fck_clk
 static struct clk vlynq_fck = {
 	.name		= "vlynq_fck",
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CM_CORE_SEL1 | DELAYED_APP,
+	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
 	.init		= &omap2_init_clksel_parent,
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -95,16 +95,7 @@ extern int clk_get_usecount(struct clk *
 #define CLOCK_NO_IDLE_PARENT	(1 << 8)
 #define DELAYED_APP		(1 << 9)	/* Delay application of clock */
 #define CONFIG_PARTICIPANT	(1 << 10)	/* Fundamental clock */
-#define CM_MPU_SEL1		(1 << 11)	/* Domain divider/source */
-#define CM_DSP_SEL1		(1 << 12)
-#define CM_GFX_SEL1		(1 << 13)
-#define CM_MODEM_SEL1		(1 << 14)
-#define CM_CORE_SEL1		(1 << 15)	/* Sets divider for many */
-#define CM_CORE_SEL2		(1 << 16)	/* sets parent for GPT */
-#define CM_WKUP_SEL1		(1 << 17)
-#define CM_PLL_SEL1		(1 << 18)
-#define CM_PLL_SEL2		(1 << 19)
-#define CM_SYSCLKOUT_SEL1	(1 << 20)
+/* bits 11-20 are currently free */
 #define CLOCK_IN_OMAP310	(1 << 21)
 #define CLOCK_IN_OMAP730	(1 << 22)
 #define CLOCK_IN_OMAP1510	(1 << 23)

-- 

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

* [PATCH 21/28] omap2 clock: call clock-specific enable/disable functions if present
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (17 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 20/28] omap2 clock: remove *_SEL* clock flags Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 22/28] omap2 clock: use custom osc_ck enable/disable routines Paul Walmsley
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add_clk_specific_enable_disable.patch --]
[-- Type: text/plain, Size: 1065 bytes --]

Call clock-specific enable/disable functions if .enable/.disable function
pointer fields are present in struct clk.  Similar to OMAP1 clock code.

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


---
 arch/arm/mach-omap2/clock.c |    8 ++++++++
 1 file changed, 8 insertions(+)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -276,6 +276,9 @@ static int _omap2_clk_enable(struct clk 
 		return 0;
 	}
 
+	if (clk->enable)
+		return clk->enable(clk);
+
 	if (unlikely(clk->enable_reg == 0)) {
 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
 		       clk->name);
@@ -315,6 +318,11 @@ static void _omap2_clk_disable(struct cl
 	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
 		return;
 
+	if (clk->disable) {
+	        clk->disable(clk);
+		return;
+	}
+
 	if (unlikely(clk == &osc_ck)) {
 		omap2_set_osc_ck(0);
 		return;

-- 

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

* [PATCH 22/28] omap2 clock: use custom osc_ck enable/disable routines
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (18 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 21/28] omap2 clock: call clock-specific enable/disable functions if present Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 23/28] omap2 clock: use standard clk->enable/disable for APLLs Paul Walmsley
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: use_custom_osc_ck_enable.patch --]
[-- Type: text/plain, Size: 3374 bytes --]

Now that we're paying attention to the .enable/.disable fields in struct 
clk, convert the osc_ck enable and disable code to use this standard
mechanism.  (osc_ck enable/disable does not technically enable or disable
the osc_ck; it actually enables/disables autoidling.)

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

---
 arch/arm/mach-omap2/clock.c |   32 +++++++++++++++-----------------
 arch/arm/mach-omap2/clock.h |    5 ++++-
 2 files changed, 19 insertions(+), 18 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -162,18 +162,26 @@ static void omap2_fixed_divisor_recalc(s
 		propagate_rate(clk);
 }
 
-static void omap2_set_osc_ck(int enable)
+static int omap2_enable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
 
 	pcc = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
 
-	if (enable)
-		prm_write_reg(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
-			      OMAP24XX_PRCM_CLKSRC_CTRL);
-	else
-		prm_write_reg(pcc | OMAP_AUTOEXTCLKMODE_MASK,
-			      OMAP24XX_PRCM_CLKSRC_CTRL);
+	prm_write_reg(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
+		      OMAP24XX_PRCM_CLKSRC_CTRL);
+
+	return 0;
+}
+
+static void omap2_disable_osc_ck(struct clk *clk)
+{
+	u32 pcc;
+
+	pcc = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
+
+	prm_write_reg(pcc | OMAP_AUTOEXTCLKMODE_MASK,
+		      OMAP24XX_PRCM_CLKSRC_CTRL);
 }
 
 /*
@@ -271,11 +279,6 @@ static int _omap2_clk_enable(struct clk 
 	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
 		return 0;
 
-	if (unlikely(clk == &osc_ck)) {
-		omap2_set_osc_ck(1);
-		return 0;
-	}
-
 	if (clk->enable)
 		return clk->enable(clk);
 
@@ -323,11 +326,6 @@ static void _omap2_clk_disable(struct cl
 		return;
 	}
 
-	if (unlikely(clk == &osc_ck)) {
-		omap2_set_osc_ck(0);
-		return;
-	}
-
 	if (clk->enable_reg == 0) {
 		/*
 		 * 'Independent' here refers to a clock which is not
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -26,7 +26,6 @@
 #include "prm_regbits_24xx.h"
 #include "cm_regbits_24xx.h"
 
-static void omap2_sys_clk_recalc(struct clk * clk);
 static void omap2_clksel_recalc(struct clk * clk);
 static void omap2_table_mpu_recalc(struct clk *clk);
 static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
@@ -42,6 +41,8 @@ static void omap2_fixed_divisor_recalc(s
 static long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 static int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate);
+static int omap2_enable_osc_ck(struct clk *clk);
+static void omap2_disable_osc_ck(struct clk *clk);
 
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
@@ -598,6 +599,8 @@ static struct clk osc_ck = {		/* (*12, *
 	.rate		= 26000000,		/* fixed up in clock init */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_FIXED | RATE_PROPAGATES,
+	.enable		= &omap2_enable_osc_ck,
+	.disable	= &omap2_disable_osc_ck,
 	.recalc		= &propagate_rate,
 };
 

-- 

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

* [PATCH 23/28] omap2 clock: use standard clk->enable/disable for APLLs
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (19 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 22/28] omap2 clock: use custom osc_ck enable/disable routines Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 24/28] omap2 clock: replace omap2_get_crystal_rate() with clock-specific recalc code Paul Walmsley
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: clean-up-apll-enable-disable.patch --]
[-- Type: text/plain, Size: 3433 bytes --]

Now that we're calling the clock-specific enable & disable code, we can
get rid of the special-case code in _omap2_clk_{enable,disable}() for the
APLLs.

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

---
 arch/arm/mach-omap2/clock.c |   20 ++++++++------------
 arch/arm/mach-omap2/clock.h |    6 ++++++
 2 files changed, 14 insertions(+), 12 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -212,7 +212,7 @@ static int omap2_wait_clock_ready(void _
 
 
 /* Enable an APLL if off */
-static void omap2_clk_fixed_enable(struct clk *clk)
+static int omap2_clk_fixed_enable(struct clk *clk)
 {
 	u32 cval, apll_mask;
 
@@ -221,7 +221,7 @@ static void omap2_clk_fixed_enable(struc
 	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 
 	if ((cval & apll_mask) == apll_mask)
-		return;   /* apll already enabled */
+		return 0;   /* apll already enabled */
 
 	cval &= ~apll_mask;
 	cval |= apll_mask;
@@ -234,6 +234,12 @@ static void omap2_clk_fixed_enable(struc
 
 	omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
 			    clk->name);
+
+	/*
+	 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
+	 * fails?
+	 */
+	return 0;
 }
 
 static void omap2_clk_wait_ready(struct clk *clk)
@@ -288,11 +294,6 @@ static int _omap2_clk_enable(struct clk 
 		return -EINVAL;
 	}
 
-	if (clk->enable_reg == OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN)) {
-		omap2_clk_fixed_enable(clk);
-		return 0;
-	}
-
 	regval32 = cm_read_reg(clk->enable_reg);
 	regval32 |= (1 << clk->enable_bit);
 	cm_write_reg(regval32, clk->enable_reg);
@@ -336,11 +337,6 @@ static void _omap2_clk_disable(struct cl
 		return;
 	}
 
-	if (clk->enable_reg == OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN)) {
-		omap2_clk_fixed_disable(clk);
-		return;
-	}
-
 	regval32 = cm_read_reg(clk->enable_reg);
 	regval32 &= ~(1 << clk->enable_bit);
 	cm_write_reg(regval32, clk->enable_reg);
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -38,6 +38,8 @@ static u32 omap2_clksel_to_divisor(struc
 static u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
 static void omap2_dpll_recalc(struct clk *clk);
 static void omap2_fixed_divisor_recalc(struct clk *clk);
+static int omap2_clk_fixed_enable(struct clk *clk);
+static void omap2_clk_fixed_disable(struct clk *clk);
 static long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 static int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate);
@@ -647,6 +649,8 @@ static struct clk apll96_ck = {
 				RATE_FIXED | RATE_PROPAGATES,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
+	.enable		= &omap2_clk_fixed_enable,
+	.disable	= &omap2_clk_fixed_disable,
 	.recalc		= &propagate_rate,
 };
 
@@ -658,6 +662,8 @@ static struct clk apll54_ck = {
 				RATE_FIXED | RATE_PROPAGATES,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
+	.enable		= &omap2_clk_fixed_enable,
+	.disable	= &omap2_clk_fixed_disable,
 	.recalc		= &propagate_rate,
 };
 

-- 

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

* [PATCH 24/28] omap2 clock: replace omap2_get_crystal_rate() with clock-specific recalc code
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (20 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 23/28] omap2 clock: use standard clk->enable/disable for APLLs Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 25/28] omap2 clock: Standardize DPLL rate recalculation with struct dpll_data Paul Walmsley
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: use_custom_osc_sys_recalc.patch --]
[-- Type: text/plain, Size: 4226 bytes --]

The OMAP2 clock framework currently uses a nonstandard function to
assign the osc_ck and sys_ck rates, omap2_get_crystal_rate().  By
using custom recalc code for these clocks, we can get rid of it and
rely on the existing clock tree recalculation process.

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

---
 arch/arm/mach-omap2/clock.c |   44 ++++++++++++++++++++++++--------------------
 arch/arm/mach-omap2/clock.h |   10 +++++-----
 2 files changed, 29 insertions(+), 25 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -112,21 +112,6 @@ static void omap2_init_clksel_parent(str
 	return;
 }
 
-/* Recalculate SYST_CLK */
-static void omap2_sys_clk_recalc(struct clk * clk)
-{
-	u32 div;
-
-	if (!cpu_is_omap34xx()) {
-		div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
-		/* Test if ext clk divided by 1 or 2 */
-		div &= OMAP_SYSCLKDIV_MASK;
-		div >>= OMAP_SYSCLKDIV_SHIFT;
-		clk->rate = (clk->parent->rate / div);
-	}
-	propagate_rate(clk);
-}
-
 static u32 omap2_get_dpll_rate(struct clk * tclk)
 {
 	long long dpll_clk;
@@ -1044,9 +1029,9 @@ static struct clk_functions omap2_clk_fu
 	.clk_disable_unused	= omap2_clk_disable_unused,
 };
 
-static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
+static u32 omap2_get_apll_clkin(void)
 {
-	u32 div, aplls, sclk = 13000000;
+	u32 aplls, sclk = 0;
 
 	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
 	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
@@ -1059,12 +1044,30 @@ static void __init omap2_get_crystal_rat
 	else if (aplls == APLLS_CLKIN_12MHZ)
 		sclk = 12000000;
 
+	return sclk;
+}
+
+static u32 omap2_get_sysclkdiv(void)
+{
+	u32 div;
+
 	div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
 	div &= OMAP_SYSCLKDIV_MASK;
 	div >>= OMAP_SYSCLKDIV_SHIFT;
 
-	osc->rate = sclk * div;
-	sys->rate = sclk;
+	return div;
+}
+
+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);
 }
 
 /*
@@ -1116,7 +1119,8 @@ int __init omap2_clk_init(void)
 		cpu_mask = RATE_IN_243X;
 
 	clk_init(&omap2_clk_functions);
-	omap2_get_crystal_rate(&osc_ck, &sys_ck);
+
+	omap2_osc_clk_recalc(&osc_ck);
 
 	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
 	     clkp++) {
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -36,6 +36,8 @@ static void omap2_init_clksel_parent(str
 static u32 omap2_clksel_get_divisor(struct clk *clk);
 static u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
 static u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
+static void omap2_osc_clk_recalc(struct clk *clk);
+static void omap2_sys_clk_recalc(struct clk *clk);
 static void omap2_dpll_recalc(struct clk *clk);
 static void omap2_fixed_divisor_recalc(struct clk *clk);
 static int omap2_clk_fixed_enable(struct clk *clk);
@@ -598,21 +600,19 @@ static struct clk func_32k_ck = {
 /* 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",
-	.rate		= 26000000,		/* fixed up in clock init */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES,
+				RATE_PROPAGATES,
 	.enable		= &omap2_enable_osc_ck,
 	.disable	= &omap2_disable_osc_ck,
-	.recalc		= &propagate_rate,
+	.recalc		= &omap2_osc_clk_recalc,
 };
 
 /* With out modem likely 12MHz, with modem likely 13MHz */
 static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
 	.name		= "sys_ck",		/* ~ ref_clk also */
 	.parent		= &osc_ck,
-	.rate		= 13000000,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+				ALWAYS_ENABLED | RATE_PROPAGATES,
 	.recalc		= &omap2_sys_clk_recalc,
 };
 

-- 

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

* [PATCH 25/28] omap2 clock: Standardize DPLL rate recalculation with struct dpll_data
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (21 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 24/28] omap2 clock: replace omap2_get_crystal_rate() with clock-specific recalc code Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 27/28] omap2 clock: add three missing clocks: gpmc_fck, sdma_{i, f}ck Paul Walmsley
  2007-08-20  9:54 ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework Paul Walmsley
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add-dpll-params-to-24xx.h --]
[-- Type: text/plain, Size: 6247 bytes --]

Introduce a new data structure, struct dpll_data, that contains DPLL
multiplier, divider, and autoidle information.  Update existing DPLL code
to use struct dpll_data.  The goal here is to set up something that will be
usable for OMAP3430 clock tree.  Note that this does not affect the SRAM DPLL 
assembly code - the DPLL register addresses are still hard-coded there.

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

---
 arch/arm/mach-omap2/clock.c       |   61 ++++++++++++++++++++++++++------------
 arch/arm/mach-omap2/clock.h       |   10 ++++++
 include/asm-arm/arch-omap/clock.h |    9 +++++
 3 files changed, 61 insertions(+), 19 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -112,20 +112,38 @@ static void omap2_init_clksel_parent(str
 	return;
 }
 
-static u32 omap2_get_dpll_rate(struct clk * tclk)
+/* Returns the DPLL rate */
+static u32 omap2_get_dpll_rate(struct clk *clk)
+{
+ 	long long dpll_clk;
+ 	u32 dpll_mult, dpll_div, dpll;
+ 	const struct dpll_data *dd;
+
+ 	dd = clk->dpll_data;
+ 	/* REVISIT: What do we return on error? */
+ 	if (!dd)
+ 		return 0;
+
+ 	dpll = cm_read_reg(dd->mult_div1_reg);
+ 	dpll_mult = dpll & dd->mult_mask;
+ 	dpll_mult >>= convert_mask_to_shift(dd->mult_mask);
+ 	dpll_div = dpll & dd->div1_mask;
+ 	dpll_div >>= convert_mask_to_shift(dd->div1_mask);
+
+ 	dpll_clk = (long long)clk->parent->rate * dpll_mult;
+ 	do_div(dpll_clk, dpll_div + 1);
+
+	return dpll_clk;
+}
+
+/* This actually returns the rate of core_ck, not dpll_ck. */
+static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
 {
 	long long dpll_clk;
-	int dpll_mult, dpll_div, amult;
-	u32 dpll;
+	u8 amult;
 
-	dpll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
+	dpll_clk = omap2_get_dpll_rate(tclk);
 
-	dpll_mult = dpll & OMAP24XX_DPLL_MULT_MASK;
-	dpll_mult >>= OMAP24XX_DPLL_MULT_SHIFT;		/* 10 bits */
-	dpll_div = dpll & OMAP24XX_DPLL_DIV_MASK;
-	dpll_div >>= OMAP24XX_DPLL_DIV_SHIFT;		/* 4 bits */
-	dpll_clk = (long long)tclk->parent->rate * dpll_mult;
-	do_div(dpll_clk, dpll_div + 1);
 	amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	amult &= OMAP24XX_CORE_CLK_SRC_MASK;
 	dpll_clk *= amult;
@@ -396,7 +414,7 @@ static u32 omap2_dpll_round_rate(unsigne
 
 static void omap2_dpll_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_dpll_rate(clk);
+	clk->rate = omap2_get_dpll_rate_24xx(clk);
 
 	propagate_rate(clk);
 }
@@ -559,10 +577,11 @@ static int omap2_reprogram_dpll(struct c
 	u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
 	u32 bypass = 0;
 	struct prcm_config tmpset;
+	const struct dpll_data *dd;
 	int ret = -EINVAL;
 
 	local_irq_save(flags);
-	cur_rate = omap2_get_dpll_rate(&dpll_ck);
+	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
 	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
@@ -580,9 +599,13 @@ static int omap2_reprogram_dpll(struct c
 		else
 			low = curr_prcm_set->dpll_speed / 2;
 
-		tmpset.cm_clksel1_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
-		tmpset.cm_clksel1_pll &= ~(OMAP24XX_DPLL_MULT_MASK |
-					   OMAP24XX_DPLL_DIV_MASK);
+		dd = clk->dpll_data;
+		if (!dd)
+			goto dpll_exit;
+
+		tmpset.cm_clksel1_pll = cm_read_reg(dd->mult_div1_reg);
+		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
+					   dd->div1_mask);
 		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
 		tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
@@ -595,8 +618,8 @@ static int omap2_reprogram_dpll(struct c
 			mult = (rate / 1000000);
 			done_rate = CORE_CLK_SRC_DPLL;
 		}
-		tmpset.cm_clksel1_pll |= (div << OMAP24XX_DPLL_DIV_SHIFT);
-		tmpset.cm_clksel1_pll |= (mult << OMAP24XX_DPLL_MULT_SHIFT);
+		tmpset.cm_clksel1_pll |= (div << convert_mask_to_shift(dd->mult_mask));
+		tmpset.cm_clksel1_pll |= (mult << convert_mask_to_shift(dd->div1_mask));
 
 		/* Worst case */
 		tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
@@ -950,7 +973,7 @@ static int omap2_select_table_rate(struc
 	}
 
 	curr_prcm_set = prcm;
-	cur_rate = omap2_get_dpll_rate(&dpll_ck);
+	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
 
 	if (prcm->dpll_speed == cur_rate / 2) {
 		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
@@ -1137,7 +1160,7 @@ int __init omap2_clk_init(void)
 	}
 
 	/* Check the MPU rate set by bootloader */
-	clkrate = omap2_get_dpll_rate(&dpll_ck);
+	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
 		if (!(prcm->flags & cpu_mask))
 			continue;
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -632,9 +632,19 @@ static struct clk alt_ck = {		/* Typical
 /* REVISIT: Rate changes on dpll_ck trigger a full set change.	...
  * deal with this
  */
+
+static const struct dpll_data dpll_dd = {
+	.mult_div1_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.mult_mask		= OMAP24XX_DPLL_MULT_MASK,
+	.div1_mask		= OMAP24XX_DPLL_DIV_MASK,
+	.auto_idle_mask		= OMAP24XX_AUTO_DPLL_MASK,
+	.auto_idle_val		= 0x3, /* stop DPLL upon idle */
+};
+
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
 	.parent		= &sys_ck,		/* Can be func_32k also */
+	.dpll_data	= &dpll_dd,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
 				RATE_PROPAGATES | ALWAYS_ENABLED,
 	.recalc		= &omap2_dpll_recalc,
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -29,6 +29,14 @@ struct clksel {
 	const struct clksel_rate *rates;
 };
 
+struct dpll_data {
+	void __iomem		*mult_div1_reg;
+	u32			mult_mask;
+	u32			div1_mask;
+	u32			auto_idle_mask;
+	u8			auto_idle_val;
+};
+
 #endif
 
 struct clk {
@@ -53,6 +61,7 @@ struct clk {
 	void __iomem		*clksel_reg;
 	u32			clksel_mask;
 	const struct clksel	*clksel;
+	const struct dpll_data	*dpll_data;
 #else
 	__u8			rate_offset;
 	__u8			src_offset;

-- 

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

* [PATCH 27/28] omap2 clock: add three missing clocks: gpmc_fck, sdma_{i, f}ck
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (22 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 25/28] omap2 clock: Standardize DPLL rate recalculation with struct dpll_data Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20  9:54 ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework Paul Walmsley
  24 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: add_24xx_gpmc_sdma_clocks.patch --]
[-- Type: text/plain, Size: 1424 bytes --]

Add three missing clocks: gpmc_fck, sdma_ick, and sdma_fck.  This is in
preparation for struct clk-based autoidling, added in the next patch.

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

---
 arch/arm/mach-omap2/clock.h |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

Index: linux-omap/arch/arm/mach-omap2/clock.h
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -2277,6 +2277,27 @@ static struct clk i2chs1_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpmc_fck = {
+	.name		= "gpmc_fck",
+	.parent		= &core_l3_ck,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk sdma_fck = {
+	.name		= "sdma_fck",
+	.parent		= &core_l3_ck,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk sdma_ick = {
+	.name		= "sdma_ick",
+	.parent		= &l4_ck,
+	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk vlynq_ick = {
 	.name		= "vlynq_ick",
 	.parent		= &core_l3_ck,
@@ -2633,6 +2654,9 @@ static struct clk *onchip_clks[] __initd
 	&i2c2_ick,
 	&i2c2_fck,
 	&i2chs2_fck,
+	&gpmc_fck,
+	&sdma_fck,
+	&sdma_ick,
 	&vlynq_ick,
 	&vlynq_fck,
 	&sdrc_ick,

-- 

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

* [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework
  2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
                   ` (23 preceding siblings ...)
  2007-08-20  9:54 ` [PATCH 27/28] omap2 clock: add three missing clocks: gpmc_fck, sdma_{i, f}ck Paul Walmsley
@ 2007-08-20  9:54 ` Paul Walmsley
  2007-08-20 12:55   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
  2007-08-20 13:18   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
  24 siblings, 2 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-20  9:54 UTC (permalink / raw)
  To: linux-omap-open-source

[-- Attachment #1: use_clk_framework_autoidle.patch --]
[-- Type: text/plain, Size: 29484 bytes --]

Existing OMAP2 code autoidles clocks via pm.c.  OMAP clock framework
already has some support for enabling autoidle mode via the allow_idle
function; however, this is currently unused.  Take advantage of this
support by adding autoidle register and bit information for each
clock, defining an omap2_clk_allow_idle() function, and adding a
framework-wide function, clk_allow_idle_all(), to autoidle all clocks,
intended to be called on init.  Remove all but the APLL/DPLL autoidle 
bit twiddling from pm.c -- we don't yet have generalized support for APLL
autoidle.  Handling autoidle via the clock framework ensures that we only
touch clocks that are currently configured.

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

---
 arch/arm/mach-omap2/clock.c           |   34 +++++++++++
 arch/arm/mach-omap2/clock.h           |  103 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/cm_regbits_24xx.h |   50 ++++++++++++++++
 arch/arm/mach-omap2/pm.c              |   63 +-------------------
 arch/arm/plat-omap/clock.c            |    9 ++
 include/asm-arm/arch-omap/clock.h     |    3 
 6 files changed, 204 insertions(+), 58 deletions(-)

Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -165,6 +165,7 @@ static void omap2_fixed_divisor_recalc(s
 		propagate_rate(clk);
 }
 
+/* REVISIT: This is really autoidle control, not enable/disable */
 static int omap2_enable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
@@ -177,6 +178,7 @@ static int omap2_enable_osc_ck(struct cl
 	return 0;
 }
 
+/* REVISIT: This is really autoidle control, not enable/disable */
 static void omap2_disable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
@@ -1023,6 +1025,34 @@ static int omap2_select_table_rate(struc
 	return 0;
 }
 
+static void omap2_clk_allow_idle(struct clk *clk)
+{
+	u32 regval;
+	u8 shift;
+	const struct dpll_data *dd;
+
+	if (clk->auto_idle_reg) {
+		regval = cm_read_reg(clk->auto_idle_reg);
+
+		if (clk->dpll_data) {
+			/* Special handling for DPLLs */
+
+			dd = clk->dpll_data;
+			if (!dd->auto_idle_mask || !dd->auto_idle_val)
+				return;
+
+			shift = convert_mask_to_shift(dd->auto_idle_mask);
+			regval &= dd->auto_idle_mask;
+			regval |= dd->auto_idle_val << shift;
+
+		} else if (clk->auto_idle_bit) {
+			regval |= (1 << clk->auto_idle_bit);
+		}
+
+		cm_write_reg(regval, clk->auto_idle_reg);
+	}
+}
+
 /*-------------------------------------------------------------------------
  * Omap2 clock reset and init functions
  *-------------------------------------------------------------------------*/
@@ -1049,6 +1079,7 @@ static struct clk_functions omap2_clk_fu
 	.clk_round_rate		= omap2_clk_round_rate,
 	.clk_set_rate		= omap2_clk_set_rate,
 	.clk_set_parent		= omap2_clk_set_parent,
+	.clk_allow_idle		= omap2_clk_allow_idle,
 	.clk_disable_unused	= omap2_clk_disable_unused,
 };
 
@@ -1184,6 +1215,9 @@ int __init omap2_clk_init(void)
 	 */
 	clk_enable_init_clocks();
 
+	/* Autoidle all clocks that can be autoidled */
+	clk_allow_idle_all();
+
 	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
 	vclk = clk_get(NULL, "virt_prcm_set");
 	sclk = clk_get(NULL, "sys_ck");
Index: linux-omap/arch/arm/mach-omap2/clock.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.h
+++ linux-omap/arch/arm/mach-omap2/clock.h
@@ -1204,6 +1204,8 @@ static struct clk usb_l4_ick = {	/* FS-U
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
 	.clksel		= usb_l4_ick_clksel,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP24XX_AUTO_USB_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate
@@ -1395,6 +1397,8 @@ static struct clk ssi_l4_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),	/* bit 1 */
 	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP24XX_AUTO_SSI_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1439,6 +1443,8 @@ static struct clk dss_ick = {		/* Enable
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_DSS_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1555,6 +1561,8 @@ static struct clk gpt2_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	/* Bit4 */
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1577,6 +1585,8 @@ static struct clk gpt3_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	/* Bit5 */
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT3_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1599,6 +1609,8 @@ static struct clk gpt4_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	/* Bit6 */
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT4_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1621,6 +1633,8 @@ static struct clk gpt5_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* Bit7 */
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT5_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1643,6 +1657,8 @@ static struct clk gpt6_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit8 */
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT6_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1665,6 +1681,8 @@ static struct clk gpt7_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit9 */
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1687,6 +1705,8 @@ static struct clk gpt8_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit10 */
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT8_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1709,6 +1729,8 @@ static struct clk gpt9_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT9_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1731,6 +1753,8 @@ static struct clk gpt10_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT10_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1753,6 +1777,8 @@ static struct clk gpt11_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT11_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1775,6 +1801,8 @@ static struct clk gpt12_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),	 /* bit14 */
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPT12_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1797,6 +1825,8 @@ static struct clk mcbsp1_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MCBSP1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1815,6 +1845,8 @@ static struct clk mcbsp2_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MCBSP2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1833,6 +1865,8 @@ static struct clk mcbsp3_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP2430_AUTO_MCBSP3_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1851,6 +1885,8 @@ static struct clk mcbsp4_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MCBSP4_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1869,6 +1905,8 @@ static struct clk mcbsp5_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MCBSP5_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1888,6 +1926,8 @@ static struct clk mcspi1_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MCSPI1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1908,6 +1948,8 @@ static struct clk mcspi2_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MCSPI2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1928,6 +1970,8 @@ static struct clk mcspi3_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MCSPI3_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1947,6 +1991,8 @@ static struct clk uart1_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_UART1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1965,6 +2011,8 @@ static struct clk uart2_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_UART2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1983,6 +2031,8 @@ static struct clk uart3_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP24XX_AUTO_UART3_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2070,6 +2120,8 @@ static struct clk cam_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_CAM_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2088,6 +2140,8 @@ static struct clk mailboxes_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MAILBOXES_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2097,6 +2151,8 @@ static struct clk wdt4_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_WDT4_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2115,6 +2171,8 @@ static struct clk wdt3_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP2420_AUTO_WDT3_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2133,6 +2191,8 @@ static struct clk mspro_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_MSPRO_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2151,6 +2211,8 @@ static struct clk mmc_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP2420_AUTO_MMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2169,6 +2231,8 @@ static struct clk fac_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_FAC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2187,6 +2251,8 @@ static struct clk eac_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP2420_AUTO_EAC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2205,6 +2271,8 @@ static struct clk hdq_ick = {
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_HDQ_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2224,6 +2292,8 @@ static struct clk i2c2_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_I2C2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2254,6 +2324,8 @@ static struct clk i2c1_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP24XX_AUTO_I2C1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2281,6 +2353,8 @@ static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE3),
+	.auto_idle_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2288,6 +2362,8 @@ static struct clk sdma_fck = {
 	.name		= "sdma_fck",
 	.parent		= &core_l3_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE3),
+	.auto_idle_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2295,6 +2371,8 @@ static struct clk sdma_ick = {
 	.name		= "sdma_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE3),
+	.auto_idle_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2304,6 +2382,8 @@ static struct clk vlynq_ick = {
 	.flags		= CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE1),
+	.auto_idle_bit	= OMAP2420_AUTO_VLYNQ_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2347,12 +2427,15 @@ static struct clk vlynq_fck = {
 	.set_rate	= &omap2_clksel_set_rate
 };
 
+/* sdrc_ick may also be in recent 2420 ES2 revisions */
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP2430_CM_ICLKEN3),
 	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE3),
+	.auto_idle_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2362,6 +2445,8 @@ static struct clk des_ick = {
 	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE4),
+	.auto_idle_bit	= OMAP24XX_AUTO_DES_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2371,6 +2456,8 @@ static struct clk sha_ick = {
 	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE4),
+	.auto_idle_bit	= OMAP24XX_AUTO_SHA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2380,6 +2467,8 @@ static struct clk rng_ick = {
 	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE4),
+	.auto_idle_bit	= OMAP24XX_AUTO_RNG_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2389,6 +2478,8 @@ static struct clk aes_ick = {
 	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE4),
+	.auto_idle_bit	= OMAP24XX_AUTO_AES_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2398,6 +2489,8 @@ static struct clk pka_ick = {
 	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_AUTOIDLE4),
+	.auto_idle_bit	= OMAP24XX_AUTO_PKA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2416,6 +2509,8 @@ static struct clk usbhs_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_USBHS_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2425,6 +2520,8 @@ static struct clk mmchs1_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MMCHS1_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2443,6 +2540,8 @@ static struct clk mmchs2_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MMCHS2_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2461,6 +2560,8 @@ static struct clk gpio5_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_GPIO5_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -2479,6 +2580,8 @@ static struct clk mdm_intc_ick = {
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
+	.auto_idle_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_AUTOIDLE2),
+	.auto_idle_bit	= OMAP2430_AUTO_MDM_INTC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
Index: linux-omap/include/asm-arm/arch-omap/clock.h
===================================================================
--- linux-omap.orig/include/asm-arm/arch-omap/clock.h
+++ linux-omap/include/asm-arm/arch-omap/clock.h
@@ -62,6 +62,8 @@ struct clk {
 	u32			clksel_mask;
 	const struct clksel	*clksel;
 	const struct dpll_data	*dpll_data;
+	void __iomem		*auto_idle_reg;
+	u8			auto_idle_bit;
 #else
 	__u8			rate_offset;
 	__u8			src_offset;
@@ -92,6 +94,7 @@ extern void clk_allow_idle(struct clk *c
 extern void clk_deny_idle(struct clk *clk);
 extern int clk_get_usecount(struct clk *clk);
 extern void clk_enable_init_clocks(void);
+extern void clk_allow_idle_all(void);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
Index: linux-omap/arch/arm/mach-omap2/pm.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/pm.c
+++ linux-omap/arch/arm/mach-omap2/pm.c
@@ -688,69 +688,16 @@ static void __init prcm_setup_regs(void)
 	cm_write_mod_reg(OMAP2420_AUTOSTATE_IVA | OMAP24XX_AUTOSTATE_DSP,
 			 OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
 
-	/* Enable clock autoidle for all domains */
-	cm_write_mod_reg(OMAP24XX_AUTO_CAM |
-			 OMAP24XX_AUTO_MAILBOXES |
-			 OMAP24XX_AUTO_WDT4 |
-			 OMAP2420_AUTO_WDT3 |
-			 OMAP24XX_AUTO_MSPRO |
-			 OMAP2420_AUTO_MMC |
-			 OMAP24XX_AUTO_FAC |
-			 OMAP2420_AUTO_EAC |
-			 OMAP24XX_AUTO_HDQ |
-			 OMAP24XX_AUTO_UART2 |
-			 OMAP24XX_AUTO_UART1 |
-			 OMAP24XX_AUTO_I2C2 |
-			 OMAP24XX_AUTO_I2C1 |
-			 OMAP24XX_AUTO_MCSPI2 |
-			 OMAP24XX_AUTO_MCSPI1 |
-			 OMAP24XX_AUTO_MCBSP2 |
-			 OMAP24XX_AUTO_MCBSP1 |
-			 OMAP24XX_AUTO_GPT12 |
-			 OMAP24XX_AUTO_GPT11 |
-			 OMAP24XX_AUTO_GPT10 |
-			 OMAP24XX_AUTO_GPT9 |
-			 OMAP24XX_AUTO_GPT8 |
-			 OMAP24XX_AUTO_GPT7 |
-			 OMAP24XX_AUTO_GPT6 |
-			 OMAP24XX_AUTO_GPT5 |
-			 OMAP24XX_AUTO_GPT4 |
-			 OMAP24XX_AUTO_GPT3 |
-			 OMAP24XX_AUTO_GPT2 |
-			 OMAP2420_AUTO_VLYNQ |
-			 OMAP24XX_AUTO_DSS,
-			 CORE_MOD, CM_AUTOIDLE1);
-	cm_write_mod_reg(OMAP24XX_AUTO_UART3 |
-			 OMAP24XX_AUTO_SSI |
-			 OMAP24XX_AUTO_USB,
-			 CORE_MOD, CM_AUTOIDLE2);
-	cm_write_mod_reg(OMAP24XX_AUTO_SDRC |
-			 OMAP24XX_AUTO_GPMC |
-			 OMAP24XX_AUTO_SDMA,
-			 CORE_MOD, OMAP24XX_CM_AUTOIDLE3);
-	cm_write_mod_reg(OMAP24XX_AUTO_PKA |
-			 OMAP24XX_AUTO_AES |
-			 OMAP24XX_AUTO_RNG |
-			 OMAP24XX_AUTO_SHA |
-			 OMAP24XX_AUTO_DES,
-			 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
-
-	cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
-
-	/* Put DPLL and both APLLs into autoidle mode */
+	/*
+	 * Put DPLL and both APLLs into autoidle mode
+	 * REVISIT: we don't handle APLL autoidle yet in the clock framework,
+	 * so we leave this here
+	 */
 	cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
 			 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
 			 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
 			 PLL_MOD, CM_AUTOIDLE);
 
-	cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL |
-			 OMAP24XX_AUTO_WDT1 |
-			 OMAP24XX_AUTO_MPU_WDT |
-			 OMAP24XX_AUTO_GPIOS |
-			 OMAP24XX_AUTO_32KSYNC |
-			 OMAP24XX_AUTO_GPT1,
-			 WKUP_MOD, CM_AUTOIDLE);
-
 	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 	 * stabilisation */
 	prm_write_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_PRCM_CLKSSETUP);
Index: linux-omap/arch/arm/plat-omap/clock.c
===================================================================
--- linux-omap.orig/arch/arm/plat-omap/clock.c
+++ linux-omap/arch/arm/plat-omap/clock.c
@@ -383,6 +383,15 @@ void clk_allow_idle(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_allow_idle);
 
+void clk_allow_idle_all(void)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &clocks, node)
+		clk_allow_idle(clkp);
+}
+EXPORT_SYMBOL(clk_allow_idle_all);
+
 void clk_enable_init_clocks(void)
 {
 	struct clk *clkp;
Index: linux-omap/arch/arm/mach-omap2/cm_regbits_24xx.h
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/cm_regbits_24xx.h
+++ linux-omap/arch/arm/mach-omap2/cm_regbits_24xx.h
@@ -141,61 +141,111 @@
 
 /* CM_AUTOIDLE1_CORE */
 #define OMAP24XX_AUTO_CAM				(1 << 31)
+#define OMAP24XX_AUTO_CAM_SHIFT				31
 #define OMAP24XX_AUTO_MAILBOXES				(1 << 30)
+#define OMAP24XX_AUTO_MAILBOXES_SHIFT			30
 #define OMAP24XX_AUTO_WDT4				(1 << 29)
+#define OMAP24XX_AUTO_WDT4_SHIFT			29
 #define OMAP2420_AUTO_WDT3				(1 << 28)
+#define OMAP2420_AUTO_WDT3_SHIFT			28
 #define OMAP24XX_AUTO_MSPRO				(1 << 27)
+#define OMAP24XX_AUTO_MSPRO_SHIFT			27
 #define OMAP2420_AUTO_MMC				(1 << 26)
+#define OMAP2420_AUTO_MMC_SHIFT				26
 #define OMAP24XX_AUTO_FAC				(1 << 25)
+#define OMAP24XX_AUTO_FAC_SHIFT				25
 #define OMAP2420_AUTO_EAC				(1 << 24)
+#define OMAP2420_AUTO_EAC_SHIFT				24
 #define OMAP24XX_AUTO_HDQ				(1 << 23)
+#define OMAP24XX_AUTO_HDQ_SHIFT				23
 #define OMAP24XX_AUTO_UART2				(1 << 22)
+#define OMAP24XX_AUTO_UART2_SHIFT			22
 #define OMAP24XX_AUTO_UART1				(1 << 21)
+#define OMAP24XX_AUTO_UART1_SHIFT			21
 #define OMAP24XX_AUTO_I2C2				(1 << 20)
+#define OMAP24XX_AUTO_I2C2_SHIFT			20
 #define OMAP24XX_AUTO_I2C1				(1 << 19)
+#define OMAP24XX_AUTO_I2C1_SHIFT			19
 #define OMAP24XX_AUTO_MCSPI2				(1 << 18)
+#define OMAP24XX_AUTO_MCSPI2_SHIFT			18
 #define OMAP24XX_AUTO_MCSPI1				(1 << 17)
+#define OMAP24XX_AUTO_MCSPI1_SHIFT			17
 #define OMAP24XX_AUTO_MCBSP2				(1 << 16)
+#define OMAP24XX_AUTO_MCBSP2_SHIFT			16
 #define OMAP24XX_AUTO_MCBSP1				(1 << 15)
+#define OMAP24XX_AUTO_MCBSP1_SHIFT			15
 #define OMAP24XX_AUTO_GPT12				(1 << 14)
+#define OMAP24XX_AUTO_GPT12_SHIFT			14
 #define OMAP24XX_AUTO_GPT11				(1 << 13)
+#define OMAP24XX_AUTO_GPT11_SHIFT			13
 #define OMAP24XX_AUTO_GPT10				(1 << 12)
+#define OMAP24XX_AUTO_GPT10_SHIFT			12
 #define OMAP24XX_AUTO_GPT9				(1 << 11)
+#define OMAP24XX_AUTO_GPT9_SHIFT			11
 #define OMAP24XX_AUTO_GPT8				(1 << 10)
+#define OMAP24XX_AUTO_GPT8_SHIFT			10
 #define OMAP24XX_AUTO_GPT7				(1 << 9)
+#define OMAP24XX_AUTO_GPT7_SHIFT			9
 #define OMAP24XX_AUTO_GPT6				(1 << 8)
+#define OMAP24XX_AUTO_GPT6_SHIFT			8
 #define OMAP24XX_AUTO_GPT5				(1 << 7)
+#define OMAP24XX_AUTO_GPT5_SHIFT			7
 #define OMAP24XX_AUTO_GPT4				(1 << 6)
+#define OMAP24XX_AUTO_GPT4_SHIFT			6
 #define OMAP24XX_AUTO_GPT3				(1 << 5)
+#define OMAP24XX_AUTO_GPT3_SHIFT			5
 #define OMAP24XX_AUTO_GPT2				(1 << 4)
+#define OMAP24XX_AUTO_GPT2_SHIFT			4
 #define OMAP2420_AUTO_VLYNQ				(1 << 3)
+#define OMAP2420_AUTO_VLYNQ_SHIFT			3
 #define OMAP24XX_AUTO_DSS				(1 << 0)
+#define OMAP24XX_AUTO_DSS_SHIFT				0
 
 /* CM_AUTOIDLE2_CORE */
 #define OMAP2430_AUTO_MDM_INTC				(1 << 11)
+#define OMAP2430_AUTO_MDM_INTC_SHIFT			11
 #define OMAP2430_AUTO_GPIO5				(1 << 10)
+#define OMAP2430_AUTO_GPIO5_SHIFT			10
 #define OMAP2430_AUTO_MCSPI3				(1 << 9)
+#define OMAP2430_AUTO_MCSPI3_SHIFT			9
 #define OMAP2430_AUTO_MMCHS2				(1 << 8)
+#define OMAP2430_AUTO_MMCHS2_SHIFT			8
 #define OMAP2430_AUTO_MMCHS1				(1 << 7)
+#define OMAP2430_AUTO_MMCHS1_SHIFT			7
 #define OMAP2430_AUTO_USBHS				(1 << 6)
+#define OMAP2430_AUTO_USBHS_SHIFT			6
 #define OMAP2430_AUTO_MCBSP5				(1 << 5)
+#define OMAP2430_AUTO_MCBSP5_SHIFT			5
 #define OMAP2430_AUTO_MCBSP4				(1 << 4)
+#define OMAP2430_AUTO_MCBSP4_SHIFT			4
 #define OMAP2430_AUTO_MCBSP3				(1 << 3)
+#define OMAP2430_AUTO_MCBSP3_SHIFT			3
 #define OMAP24XX_AUTO_UART3				(1 << 2)
+#define OMAP24XX_AUTO_UART3_SHIFT			2
 #define OMAP24XX_AUTO_SSI				(1 << 1)
+#define OMAP24XX_AUTO_SSI_SHIFT				1
 #define OMAP24XX_AUTO_USB				(1 << 0)
+#define OMAP24XX_AUTO_USB_SHIFT				0
 
 /* CM_AUTOIDLE3_CORE */
 #define OMAP24XX_AUTO_SDRC				(1 << 2)
+#define OMAP24XX_AUTO_SDRC_SHIFT			2
 #define OMAP24XX_AUTO_GPMC				(1 << 1)
+#define OMAP24XX_AUTO_GPMC_SHIFT			1
 #define OMAP24XX_AUTO_SDMA				(1 << 0)
+#define OMAP24XX_AUTO_SDMA_SHIFT			0
 
 /* CM_AUTOIDLE4_CORE */
 #define OMAP24XX_AUTO_PKA				(1 << 4)
+#define OMAP24XX_AUTO_PKA_SHIFT				4
 #define OMAP24XX_AUTO_AES				(1 << 3)
+#define OMAP24XX_AUTO_AES_SHIFT				3
 #define OMAP24XX_AUTO_RNG				(1 << 2)
+#define OMAP24XX_AUTO_RNG_SHIFT				2
 #define OMAP24XX_AUTO_SHA				(1 << 1)
+#define OMAP24XX_AUTO_SHA_SHIFT				1
 #define OMAP24XX_AUTO_DES				(1 << 0)
+#define OMAP24XX_AUTO_DES_SHIFT				0
 
 /* CM_CLKSEL1_CORE */
 #define OMAP24XX_CLKSEL_USB_SHIFT			25

-- 

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

* RE: [PATCH 07/28] omap2 clock: init clksel clock parents to hardwarereality at clock init
  2007-08-20  9:53 ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardware reality at clock init Paul Walmsley
@ 2007-08-20 12:27   ` Woodruff, Richard
  2007-08-21  6:49     ` Paul Walmsley
  0 siblings, 1 reply; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-20 12:27 UTC (permalink / raw)
  To: Paul Walmsley, linux-omap-open-source

Paul,

This will be a nice addition and was hole. Thanks.

Karthik added this type function for OMAP3 on its first go around.
Might be worth looking at that also. I don't think he did it via the
.init function.

BTW: Do you know if OMAP1 has this function, I don't think it used to.

In OMAP3 right now there has been a strong push to pull out much of the
register accesses into a lower layer.  This sets up for higher
compatibility in the face of multiple changes which may come in some
OMAP3 variants and OMAP4.  Trying to extend the access macros to account
for widely changing implementations but with similar concepts does not
provide enough flexibility.

Regards,
Richard W.

> Source-selectable clksel clocks have a 'default parent' assigned to
them
> at compile-time.  This default parent may or may not match the reality
> that is configured in the hardware registers by the bootloader.  Clock
> tree
> recalculations could be erratic if the struct clk parent field
contents
> don't match the hardware registers.
> 
> Resolve this by creating omap2_init_clksel_parent() to read the
hardware
> registers and update the struct clk parent field as appropriate for
clksel
> clocks.  Add an '.init' field to each source-selectable clk structure
so
> that the parent is fixed up when the clock is initially registered.
(We
> don't do this for clksel clocks that are only rate-selectable, since
they
> only have one possible parent clock.)
> 
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> 
> ---
>  arch/arm/mach-omap2/clock.c |   58
> ++++++++++++++++++++++++++++++++++++++++----
>  arch/arm/mach-omap2/clock.h |   22 ++++++++++++++++
>  2 files changed, 75 insertions(+), 5 deletions(-)
> 
> Index: linux-omap/arch/arm/mach-omap2/clock.c
> Index: linux-omap/arch/arm/mach-omap2/clock.c
> ===================================================================
> --- linux-omap.orig/arch/arm/mach-omap2/clock.c
> +++ linux-omap/arch/arm/mach-omap2/clock.c
> @@ -93,6 +93,54 @@ static u32 sysclkout_div[] = {1, 2, 4, 8
>   * Omap2 specific clock functions
>
*-----------------------------------------------------------------------
> --*/
> 
> +static inline u8 convert_mask_to_shift(u32 mask) {
> +	return ffs(mask) - 1;
> +}
> +
> +/**
> + * omap2_init_clksel_parent - set a clksel clk's parent field from
the
> hardware
> + * @clk: OMAP clock struct ptr to use
> + *
> + * Given a pointer to a source-selectable struct clk, read the
hardware
> + * register and determine what its parent is currently set to.
Update
> the
> + * clk->parent field with the appropriate clk ptr.
> + */
> +static void omap2_init_clksel_parent(struct clk *clk)
> +{
> +	const struct clksel *clks;
> +	const struct clksel_rate *clkr;
> +	u32 r, found = 0;
> +
> +	if (!clk->clksel)
> +		return;
> +
> +	/* XXX Should be __raw_readl for non-CM 3430 clocks ? */
> +	r = cm_read_reg(clk->clksel_reg) & clk->clksel_mask;
> +	r >>= convert_mask_to_shift(clk->clksel_mask);
> +
> +	for (clks = clk->clksel; clks->parent && !found; clks++) {
> +		for (clkr = clks->rates; clkr->div && !found; clkr++) {
> +			if ((clkr->flags & cpu_mask) && (clkr->val ==
r)) {
> +				if (clk->parent != clks->parent) {
> +					pr_debug("clock: inited %s
parent "
> +						 "to %s (was %s)\n",
> +						 clk->name,
clks->parent->name,
> +						 ((clk->parent->name) ?
> +						  clk->parent->name :
"NULL"));
> +					clk->parent = clks->parent;
> +				};
> +				found = 1;
> +			}
> +		}
> +	}
> +
> +	if (!found)
> +		printk(KERN_ERR "clock: init parent: could not find "
> +		       "regval %0x for clock %s\n", r,  clk->name);
> +
> +	return;
> +}
> +
>  /* Recalculate SYST_CLK */
>  static void omap2_sys_clk_recalc(struct clk * clk)
>  {
> @@ -1193,6 +1241,11 @@ int __init omap2_clk_init(void)
>  	struct clk ** clkp;
>  	u32 clkrate;
> 
> +	if (cpu_is_omap242x())
> +		cpu_mask = RATE_IN_242X;
> +	else if (cpu_is_omap2430())
> +		cpu_mask = RATE_IN_243X;
> +
>  	clk_init(&omap2_clk_functions);
>  	omap2_get_crystal_rate(&osc_ck, &sys_ck);
> 
> @@ -1210,11 +1263,6 @@ int __init omap2_clk_init(void)
>  		}
>  	}
> 
> -	if (cpu_is_omap242x())
> -		cpu_mask = RATE_IN_242X;
> -	else if (cpu_is_omap2430())
> -		cpu_mask = RATE_IN_243X;
> -
>  	/* Check the MPU rate set by bootloader */
>  	clkrate = omap2_get_dpll_rate(&dpll_ck);
>  	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
> Index: linux-omap/arch/arm/mach-omap2/clock.h
> ===================================================================
> --- linux-omap.orig/arch/arm/mach-omap2/clock.h
> +++ linux-omap/arch/arm/mach-omap2/clock.h
> @@ -29,6 +29,7 @@ static int omap2_select_table_rate(struc
>  static long omap2_round_to_table_rate(struct clk * clk, unsigned long
> rate);
>  static void omap2_clk_disable(struct clk *clk);
>  static void omap2_sys_clk_recalc(struct clk * clk);
> +static void omap2_init_clksel_parent(struct clk *clk);
>  static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
>  static u32 omap2_clksel_get_divisor(struct clk *clk);
>  static void omap2_dpll_recalc(struct clk *clk);
> @@ -690,6 +691,7 @@ static struct clk func_54m_ck = {
>  				RATE_FIXED | CM_PLL_SEL1 |
RATE_PROPAGATES |
>  				PARENT_CONTROLS_CLOCK,
>  	.src_offset	= OMAP24XX_54M_SOURCE_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP24XX_54M_SOURCE,
>  	.clksel		= func_54m_clksel,
> @@ -729,6 +731,7 @@ static struct clk func_96m_ck = {
>  	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
>  				RATE_FIXED | RATE_PROPAGATES |
>  				PARENT_CONTROLS_CLOCK,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP2430_96M_SOURCE,
>  	.clksel		= func_96m_clksel,
> @@ -761,6 +764,7 @@ static struct clk func_48m_ck = {
>  				RATE_FIXED | CM_PLL_SEL1 |
RATE_PROPAGATES |
>  				PARENT_CONTROLS_CLOCK,
>  	.src_offset	= OMAP24XX_48M_SOURCE_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP24XX_48M_SOURCE,
>  	.clksel		= func_48m_clksel,
> @@ -830,6 +834,7 @@ static struct clk sys_clkout_src = {
>  	.src_offset	= OMAP24XX_CLKOUT_SOURCE_SHIFT,
>  	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
>  	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
>  	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
>  	.clksel		= common_clkout_src_clksel,
> @@ -872,6 +877,7 @@ static struct clk sys_clkout2_src = {
>  				RATE_PROPAGATES,
>  	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
>  	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
>  	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
>  	.clksel		= common_clkout_src_clksel,
> @@ -937,6 +943,7 @@ static struct clk mpu_ck = {	/* Control
>  				ALWAYS_ENABLED | CM_MPU_SEL1 |
DELAYED_APP |
>  				CONFIG_PARTICIPANT | RATE_PROPAGATES,
>  	.rate_offset	= OMAP24XX_CLKSEL_MPU_SHIFT,	/* bits 0-4 */
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
>  	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
>  	.clksel		= mpu_clksel,
> @@ -1431,6 +1438,7 @@ static struct clk dss1_fck = {
>  	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
>  	.rate_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_DSS1_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
>  	.clksel		= dss1_fck_clksel,
> @@ -1462,6 +1470,7 @@ static struct clk dss2_fck = {		/* Alt c
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_DSS2_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
>  	.clksel		= dss2_fck_clksel,
> @@ -1522,6 +1531,7 @@ static struct clk gpt1_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, OMAP24XX_CM_FCLKEN),
/*
> Bit0 */
>  	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT1_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1545,6 +1555,7 @@ static struct clk gpt2_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT2_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1568,6 +1579,7 @@ static struct clk gpt3_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT3_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1591,6 +1603,7 @@ static struct clk gpt4_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT4_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1614,6 +1627,7 @@ static struct clk gpt5_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT5_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1637,6 +1651,7 @@ static struct clk gpt6_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT6_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1660,6 +1675,7 @@ static struct clk gpt7_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT7_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1683,6 +1699,7 @@ static struct clk gpt8_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT8_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1706,6 +1723,7 @@ static struct clk gpt9_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT9_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1729,6 +1747,7 @@ static struct clk gpt10_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT10_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1752,6 +1771,7 @@ static struct clk gpt11_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT11_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
>  	.clksel		= gpt_clksel,
> @@ -1775,6 +1795,7 @@ static struct clk gpt12_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
>  	.src_offset	= OMAP24XX_CLKSEL_GPT12_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
>  	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
>  	.clksel		= gpt_clksel,
> @@ -2308,6 +2329,7 @@ static struct clk vlynq_fck = {
>  	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
>  	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
>  	.src_offset	= OMAP2420_CLKSEL_VLYNQ_SHIFT,
> +	.init		= &omap2_init_clksel_parent,
>  	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
>  	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
>  	.clksel		= vlynq_fck_clksel,
> 
> --
> 
> _______________________________________________
> Linux-omap-open-source mailing list
> Linux-omap-open-source@linux.omap.com
> http://linux.omap.com/mailman/listinfo/linux-omap-open-source

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-20  9:54 ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework Paul Walmsley
@ 2007-08-20 12:55   ` Woodruff, Richard
  2007-08-21  7:04     ` Paul Walmsley
  2007-08-23  9:21     ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe " Tuukka.Tikkanen
  2007-08-20 13:18   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
  1 sibling, 2 replies; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-20 12:55 UTC (permalink / raw)
  To: Paul Walmsley, linux-omap-open-source

Hi Paul,

> Existing OMAP2 code autoidles clocks via pm.c.  OMAP clock framework
> already has some support for enabling autoidle mode via the allow_idle
> function; however, this is currently unused.  Take advantage of this
> support by adding autoidle register and bit information for each
> clock, defining an omap2_clk_allow_idle() function, and adding a
> framework-wide function, clk_allow_idle_all(), to autoidle all clocks,
> intended to be called on init.  Remove all but the APLL/DPLL autoidle
> bit twiddling from pm.c -- we don't yet have generalized support for
APLL
> autoidle.  Handling autoidle via the clock framework ensures that we
only
> touch clocks that are currently configured.

I thought about doing this back when OMAP1 added this when I was more
active on OMAP2.  However, I dropped it as it didn't have enough 'bang'
in this form.  I think these registers (even in OMAP1) are widely
mis-understood.  This is partially a TRM issue and one of complexity.

Meaning you can set this register on a per-clock basis however they do
nothing for run time except at L3/L4 domain change time.  In the
OMAP-GIT code this means at retention time the PRCM has permission to
shut off your ICLK assuming your module acknowledges it.  If the PM code
does this manually (enable/disable) then this register has no effect.

It does have a useful run time property in that it is one form to gate a
clock stop state assuming you have not forced it.  This is one way to
stop a cascade clock stop from happening when you are not expecting it.
It would be a lighter weight way then the mutex which OMAP2-GIT code
uses.  However, for that to work other code would have to change.

Each IP-Module _does_ have an AUTOIDLE bit in its SYSCONIG space which
does act as you might expect this bit to.  Setting this AUTOIDLE does
save significant power.  It would be more useful to control that one
from here.  

If you hook up a current meter you can toggle all the CM_AUTOIDLES you
like and nothing will happen.  But if you do the same with the module
autoidle you will see a bit change.

Regards,
Richard W.

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-20  9:54 ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework Paul Walmsley
  2007-08-20 12:55   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
@ 2007-08-20 13:18   ` Woodruff, Richard
  2007-08-20 13:30     ` Igor Stoppa
  1 sibling, 1 reply; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-20 13:18 UTC (permalink / raw)
  To: Paul Walmsley, linux-omap-open-source


One further note is in the 'ideal' model you should never have to
control your I-CLK at all just your F-CLK.  I'm sure our hardware people
would be very pleased if the code moved in that direction (me too if it
turned out to all work).  They generally dislike the idea of the clock
frame work as they feel it allows duplication of work the hardware can
do if setup properly.  Its APIs open up some choices which can nullify
or reduce understanding of hardware capabilities. For OMAP1 there was no
other way.  For OMAP2/3 there are some options. I do very much like the
frame work but do understand their points.

Ideally, you set all idles at all levels and all async interrupt wake
and use the PRCM interrupt to clear status at wake up time, then the
system can handle all clocks based on dependency.  Iclocks can be
managed automatically.  Fclocks should be dynamically controlled by
drivers on a demand basis.  This means some activity timers.  When this
does work the savings are really massive and dramatic.  The catch in it
is that one dependency break from a bad driver (sw or hw) at any of the
multiple levels will stop it from working.  Looking at that way rather
than OMAP1 compatibility results in something which looks a bit
different. 

Regards,
Richard W.


> Hi Paul,
> 
> > Existing OMAP2 code autoidles clocks via pm.c.  OMAP clock framework
> > already has some support for enabling autoidle mode via the
allow_idle
> > function; however, this is currently unused.  Take advantage of this
> > support by adding autoidle register and bit information for each
> > clock, defining an omap2_clk_allow_idle() function, and adding a
> > framework-wide function, clk_allow_idle_all(), to autoidle all
clocks,
> > intended to be called on init.  Remove all but the APLL/DPLL
autoidle
> > bit twiddling from pm.c -- we don't yet have generalized support for
> APLL
> > autoidle.  Handling autoidle via the clock framework ensures that we
> only
> > touch clocks that are currently configured.
> 
> I thought about doing this back when OMAP1 added this when I was more
> active on OMAP2.  However, I dropped it as it didn't have enough
'bang' in
> this form.  I think these registers (even in OMAP1) are widely mis-
> understood.  This is partially a TRM issue and one of complexity.
> 
> Meaning you can set this register on a per-clock basis however they do
> nothing for run time except at L3/L4 domain change time.  In the
OMAP-GIT
> code this means at retention time the PRCM has permission to shut off
your
> ICLK assuming your module acknowledges it.  If the PM code does this
> manually (enable/disable) then this register has no effect.
> 
> It does have a useful run time property in that it is one form to gate
a
> clock stop state assuming you have not forced it.  This is one way to
stop
> a cascade clock stop from happening when you are not expecting it.  It
> would be a lighter weight way then the mutex which OMAP2-GIT code
uses.
> However, for that to work other code would have to change.
> 
> Each IP-Module _does_ have an AUTOIDLE bit in its SYSCONIG space which
> does act as you might expect this bit to.  Setting this AUTOIDLE does
save
> significant power.  It would be more useful to control that one from
here.
> 
> If you hook up a current meter you can toggle all the CM_AUTOIDLES you
> like and nothing will happen.  But if you do the same with the module
> autoidle you will see a bit change.
> 
> Regards,
> Richard W.

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-20 13:18   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
@ 2007-08-20 13:30     ` Igor Stoppa
  2007-08-20 13:48       ` [PATCH 28/28] omap2 clock: handle (almost) all clockautoidling " Woodruff, Richard
  0 siblings, 1 reply; 41+ messages in thread
From: Igor Stoppa @ 2007-08-20 13:30 UTC (permalink / raw)
  To: ext Woodruff, Richard; +Cc: Paul Walmsley, linux-omap-open-source

On Mon, 2007-08-20 at 08:18 -0500, ext Woodruff, Richard wrote:
> One further note is in the 'ideal' model you should never have to
> control your I-CLK at all just your F-CLK.  I'm sure our hardware people
> would be very pleased if the code moved in that direction (me too if it
> turned out to all work).  They generally dislike the idea of the clock
> frame work as they feel it allows duplication of work the hardware can
> do if setup properly.  Its APIs open up some choices which can nullify
> or reduce understanding of hardware capabilities. For OMAP1 there was no
> other way.  For OMAP2/3 there are some options. I do very much like the
> frame work but do understand their points.
> 
> Ideally, you set all idles at all levels and all async interrupt wake
> and use the PRCM interrupt to clear status at wake up time, then the
> system can handle all clocks based on dependency.  Iclocks can be
> managed automatically.  Fclocks should be dynamically controlled by
> drivers on a demand basis.  This means some activity timers. 

I'm not new to these concepts, however I find extremely hard to accept
the idea of using timers, since they assume to know what the duration of
the activity will be.

Could that work on an internet tablet?
For the tablet there is not really a set of use-cases like on a phone,
where you can have a closed set of fapplications and do some serious
profiling.

>  When this
> does work the savings are really massive and dramatic.  The catch in it
> is that one dependency break from a bad driver (sw or hw) at any of the
> multiple levels will stop it from working. 

And how easy is it to trace that? All the refcounting seems to be done
in HW ...

-- 
Cheers, Igor

Igor Stoppa <igor.stoppa@nokia.com>
(Nokia Multimedia - CP - OSSO / Helsinki, Finland)

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clockautoidling viathe clock framework
  2007-08-20 13:30     ` Igor Stoppa
@ 2007-08-20 13:48       ` Woodruff, Richard
  0 siblings, 0 replies; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-20 13:48 UTC (permalink / raw)
  To: Igor Stoppa; +Cc: Paul Walmsley, linux-omap-open-source

> From: Igor Stoppa [mailto:igor.stoppa@nokia.com]
> On Mon, 2007-08-20 at 08:18 -0500, ext Woodruff, Richard wrote:
> > One further note is in the 'ideal' model you should never have to
> > control your I-CLK at all just your F-CLK.  I'm sure our hardware
people
> > would be very pleased if the code moved in that direction (me too if
it
> > turned out to all work).  They generally dislike the idea of the
clock
> > frame work as they feel it allows duplication of work the hardware
can
> > do if setup properly.  Its APIs open up some choices which can
nullify
> > or reduce understanding of hardware capabilities. For OMAP1 there
was no
> > other way.  For OMAP2/3 there are some options. I do very much like
the
> > frame work but do understand their points.
> >
> > Ideally, you set all idles at all levels and all async interrupt
wake
> > and use the PRCM interrupt to clear status at wake up time, then the
> > system can handle all clocks based on dependency.  Iclocks can be
> > managed automatically.  Fclocks should be dynamically controlled by
> > drivers on a demand basis.  This means some activity timers.
> 
> I'm not new to these concepts, however I find extremely hard to accept
> the idea of using timers, since they assume to know what the duration
of
> the activity will be.

Activity timers on your FCLKS.  Many of the Fclks can be tied to input
activity and screen blanking.  The rest of the clocks are set to driver
activity.  For some drivers like MMC this isn't so bad as you talk to
the device.  The main issue with these is making the clock usage well
behaved.

The last set of drivers like UART (or Irda) are a bit more tricky as you
much make sure the protocol can send a 'wakeup' packet.  If the
peripheral and its firmware work to spec and all code is right there is
a chance.  There are just a lot of details.  Many of them can sort out
such that it can work.

> Could that work on an internet tablet?

You can still optimized for some big usecases which you know about.
Screen blanking type things.  MP3 is a favorite one to talk about.
Other things can only be as good as they can be.

One catch in some of these like low power refresh is you much recognize
when you are there and adjust some parameters (like FIFO).  Once you do
this you are at really good power.  This kind of activity timer is ok.
What is needed is some notion of cost around some of these
optimizations.  Latency API and some extension can help make the choice
for the few major cases it matters at.

> For the tablet there is not really a set of use-cases like on a phone,
> where you can have a closed set of fapplications and do some serious
> profiling.

You can't compete with a closed system for sure in optimizations.  But
because you can't be a 200uA all the time doesn't mean you should settle
for 200mA when you could be a 10mA.

Applying such control in fast moving open source is another level of
challenge.

> >  When this
> > does work the savings are really massive and dramatic.  The catch in
it
> > is that one dependency break from a bad driver (sw or hw) at any of
the
> > multiple levels will stop it from working.
> 
> And how easy is it to trace that? All the refcounting seems to be done
> in HW ...

Not so easy.  This was one of the arguments of using a lower layer below
the clock frame work.  You can catch traces going in and out and send
them off to simulation.

Hitting the states has been prototyped and proven on HLOS's so it can
happen.  It is not just a completely static validation level test.

Regards,
Richard W.

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

* RE: [PATCH 07/28] omap2 clock: init clksel clock parents to hardwarereality at clock init
  2007-08-20 12:27   ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardwarereality " Woodruff, Richard
@ 2007-08-21  6:49     ` Paul Walmsley
  0 siblings, 0 replies; 41+ messages in thread
From: Paul Walmsley @ 2007-08-21  6:49 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: linux-omap-open-source

On Mon, 20 Aug 2007, Woodruff, Richard wrote:

> BTW: Do you know if OMAP1 has this function, I don't think it used to.

No, just took a quick look, it doesn't seem to.


- Paul

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-20 12:55   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
@ 2007-08-21  7:04     ` Paul Walmsley
  2007-08-21 17:29       ` Woodruff, Richard
  2007-08-23  9:21     ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe " Tuukka.Tikkanen
  1 sibling, 1 reply; 41+ messages in thread
From: Paul Walmsley @ 2007-08-21  7:04 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: linux-omap-open-source

Hi Richard,

On Mon, 20 Aug 2007, Woodruff, Richard wrote:

> I thought about doing this back when OMAP1 added this when I was more
> active on OMAP2.  However, I dropped it as it didn't have enough 'bang'
> in this form.  I think these registers (even in OMAP1) are widely
> mis-understood.  This is partially a TRM issue and one of complexity.
>
> Meaning you can set this register on a per-clock basis however they do
> nothing for run time except at L3/L4 domain change time.  In the
> OMAP-GIT code this means at retention time the PRCM has permission to
> shut off your ICLK assuming your module acknowledges it.

I see.  Thanks for the explanation.  So in practical terms, it seems best 
to just enable this for all clocks unconditionally, as before in pm.c, no?

> If the PM code
> does this manually (enable/disable) then this register has no effect.

So, if the clock's enable/disable bit in its ICLKEN register is touched in 
any way, the clock auto-idle bit is ignored?  Does that hidden state 
persist until reset?

> It does have a useful run time property in that it is one form to gate a
> clock stop state assuming you have not forced it.  This is one way to
> stop a cascade clock stop from happening when you are not expecting it.
> It would be a lighter weight way then the mutex which OMAP2-GIT code
> uses.  However, for that to work other code would have to change.

But that would only happen when going to retention or off, correct?

> Each IP-Module _does_ have an AUTOIDLE bit in its SYSCONIG space which
> does act as you might expect this bit to.  Setting this AUTOIDLE does
> save significant power.  It would be more useful to control that one
> from here.

Those cover potentially large numbers of clocks...  So in lieu of a more 
general power domain API, is there a reason not to set all of those bits 
unconditionally in pm.c?


- Paul

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-21  7:04     ` Paul Walmsley
@ 2007-08-21 17:29       ` Woodruff, Richard
  2007-08-22  9:49         ` Paul Walmsley
  0 siblings, 1 reply; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-21 17:29 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-omap-open-source

Hi Paul,

> On Mon, 20 Aug 2007, Woodruff, Richard wrote:
> 
> > I thought about doing this back when OMAP1 added this when I was more
> > active on OMAP2.  However, I dropped it as it didn't have enough 'bang'
> > in this form.  I think these registers (even in OMAP1) are widely
> > mis-understood.  This is partially a TRM issue and one of complexity.
> >
> > Meaning you can set this register on a per-clock basis however they do
> > nothing for run time except at L3/L4 domain change time.  In the
> > OMAP-GIT code this means at retention time the PRCM has permission to
> > shut off your ICLK assuming your module acknowledges it.
> 
> I see.  Thanks for the explanation.  So in practical terms, it seems best
> to just enable this for all clocks unconditionally, as before in pm.c, no?

Probably so... Given the current surrounding implementation it is not so effective and will result in many drivers adding some calls which are just noise. Hollow code...

I think even in OMAP1 a similar condition exists, it's been a long while since I looked.  But its clock manager bits also allowed auto control during only full domain changes to its couple of sleep modes.  One can consider an OMAP1 as only have a single big domain where and OMAP2 as several and an OMAP3 has many.  Some ideas and techniques have been carried forward.

Like I was indicating for OMAP2/3 if the PRCM auto idle was switched with the module auto-idle it would not be noise it would be substantive.
	-- One issue here is the address range for this bit is with each driver in the _generic_ IP OCP (open core protocol bus interface) wrapper header.  To write to this you need i+f clock on.  It still helps to set this bit even if the module is off as the clock tree can still be active and dissipating some power in the module.
	-- This is what the patch I sent out a while back was about (RFC/PATCH) to just enable all of these.  It did save a lot of power.
	-- A PRCM library can provide these access functions
	-- It can be in lined in ever driver
	-- Or the clock frame work can provide an interface for it.
	** As its generic and symmetric for every IP in the OCP wrapper I personally like to stick it all in one spot inside of adding a bunch of defines to every driver.
	** Recently we internally were debating a bit about if an API was needed as you really in some cases do need to set the CLOCKACTIVITY bits in the OCP wrapper depending on the drivers mode of activity.

> > If the PM code
> > does this manually (enable/disable) then this register has no effect.
> 
> So, if the clock's enable/disable bit in its ICLKEN register is touched in
> any way, the clock auto-idle bit is ignored?  Does that hidden state
> persist until reset?

No, not the way I read your question.

When ICLKEN is enabled and the PRCM-auto-idle is enabled hardware can manage that clock at domain change time assuming the peripheral handshakes it ok (force/no/smart).

If the ICLKEN is disabled the setting of PRCM-auto-idle has no effect.
 
> > It does have a useful run time property in that it is one form to gate a
> > clock stop state assuming you have not forced it.  This is one way to
> > stop a cascade clock stop from happening when you are not expecting it.
> > It would be a lighter weight way then the mutex which OMAP2-GIT code
> > uses.  However, for that to work other code would have to change.
> 
> But that would only happen when going to retention or off, correct?

Given the current OMAP-GIT code this is correct.  

However this is a bit more to it than that.  These clocks can be auto-handled during clock domain stop mode.  The power domains have the properties of On/Retention/Off while the clock domains have properties of On/Inactive.

The i-clocks controlled by prcm-autoidle can be hardware managed (shut down) when the L3 and L4 clock domains go inactive.  The power domains can be in any state at this time.  As it likely turns out in the GIT code today, the L3/L4 clock domain and the core power domain effectively state change at the same time.

One of the big target states for big power savings is this so called 'partially' active state.  In this case you do want the clock domains and the power domains states to not be in sync.  The L3/L4 can be stopped, but say an F-Clock to a McBSP can still be running pushing data out to a codec.  If programmed up correctly, the codec need for data can automatically signal the prcm to re-activate the L3/L4 then allow the new data to flow.  This is the 10mA vs. 200mA kind of thing I was describing (you do need to clear the wake up status for it to happen again).  When you hit 'retention' or OFF your currents are in the 50-100uA range, but there is absolutely no activity.

> > Each IP-Module _does_ have an AUTOIDLE bit in its SYSCONIG space which
> > does act as you might expect this bit to.  Setting this AUTOIDLE does
> > save significant power.  It would be more useful to control that one
> > from here.
> 
> Those cover potentially large numbers of clocks...  So in lieu of a more
> general power domain API, is there a reason not to set all of those bits
> unconditionally in pm.c?

In the general case for this bit it turns out that you can set it at init time.  Some bug work around might require some access.

However, other bits in the same range CLOCKACTIVTY do have a bit more need of dynamic access.  WE enable also might be conditionally set.  Also the handshakes sometimes take different settings (smart/force/no-idle/standby) for some bug work arounds (software or hardware).  A force idle might clear some internal status in say a HSMMC which a driver didn't fully clear out.

Regards,
Richard W.

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-21 17:29       ` Woodruff, Richard
@ 2007-08-22  9:49         ` Paul Walmsley
  2007-08-22 21:25           ` Woodruff, Richard
  0 siblings, 1 reply; 41+ messages in thread
From: Paul Walmsley @ 2007-08-22  9:49 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: linux-omap-open-source

Hi Richard,

On Tue, 21 Aug 2007, Woodruff, Richard wrote:

> Like I was indicating for OMAP2/3 if the PRCM auto idle was switched 
> with the module auto-idle it would not be noise it would be substantive.

It sounds like one doesn't even need to switch these bits, once we turn 
them on, correct?  Just enable *_SYSCONFIG autoidle and ICLK autoidle at 
boot in pm.c, and then never disable them, with no ill effects.  Some 
extra latency perhaps?  Drivers that need to toggle them to work around 
some hardware bug can just do that themselves, for the time being...

> 	-- One issue here is the address range for this bit is with each 
> driver in the _generic_ IP OCP (open core protocol bus interface) 
> wrapper header.  To write to this you need i+f clock on.  It still helps 
> to set this bit even if the module is off as the clock tree can still be 
> active and dissipating some power in the module.

You're talking about the *_SYSCONFIG autoidle bits here, right?  So to set 
those properly we'd need to walk the clock tree, enabling module clocks 
and setting the *_SYSCONFIG autoidle bit, then powering the module clocks 
back down again?

> 	-- This is what the patch I sent out a while back was about 
> (RFC/PATCH) to just enable all of these.  It did save a lot of power.

I just took another look at that patch.  The only downside is latency, 
right?  Are you thinking about updating the patch for the new PRCM access 
code?  That would make it much easier to test...

> 	** As its generic and symmetric for every IP in the OCP wrapper I 
> personally like to stick it all in one spot inside of adding a bunch of 
> defines to every driver.

Since all of those registers are in SCM space, perhaps an scm.h/scm.c file 
might be useful here.  I've been running into this with CONTROL_DEVCONF* 
on 3430 code.  I don't think the *_SYSCONFIG powersave bits fit well into 
the clock framework, so we should probably place it outside the clocks. 
I do think it would make sense to specifically encode the power domain 
that each clock resides in into the struct clk, for use by PM or SCM code.

> 	** Recently we internally were debating a bit about if an API was 
> needed as you really in some cases do need to set the CLOCKACTIVITY bits 
> in the OCP wrapper depending on the drivers mode of activity.

I've been looking at these CLOCKACTIVITY bits and am not clear on the 
intended use.  They are read-only in many modules, at least according to 
the TRM.  There is a notation about "Clock activity during wakeup mode 
period" -- could you elaborate about what that means?

> When ICLKEN is enabled and the PRCM-auto-idle is enabled hardware can 
> manage that clock at domain change time assuming the peripheral 
> handshakes it ok (force/no/smart).
>
> If the ICLKEN is disabled the setting of PRCM-auto-idle has no effect.

Okay, makes sense.

> One of the big target states for big power savings is this so called 
> 'partially' active state.  In this case you do want the clock domains 
> and the power domains states to not be in sync.  The L3/L4 can be 
> stopped, but say an F-Clock to a McBSP can still be running pushing data 
> out to a codec.  If programmed up correctly, the codec need for data can 
> automatically signal the prcm to re-activate the L3/L4 then allow the 
> new data to flow.

This is via the WKDEP/SLEEPDEP registers, correct?  or is this via another 
mechanism?

> However, other bits in the same range CLOCKACTIVTY do have a bit more 
> need of dynamic access.  WE enable also might be conditionally set.

Sorry, you lost me there - what is WE enable?


Thanks for all of the detailed information, Richard,

- Paul

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-22  9:49         ` Paul Walmsley
@ 2007-08-22 21:25           ` Woodruff, Richard
  2007-08-27  7:39             ` Paul Walmsley
  0 siblings, 1 reply; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-22 21:25 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-omap-open-source

Hi Paul,

> From: paul@utopia.booyaka.com [mailto:paul@utopia.booyaka.com] On
Behalf
> > Like I was indicating for OMAP2/3 if the PRCM auto idle was switched
> > with the module auto-idle it would not be noise it would be
substantive.
> 
> It sounds like one doesn't even need to switch these bits, once we
turn
> them on, correct?  Just enable *_SYSCONFIG autoidle and ICLK autoidle
at
> boot in pm.c, and then never disable them, with no ill effects.  Some
> extra latency perhaps?  Drivers that need to toggle them to work
around
> some hardware bug can just do that themselves, for the time being...

Yes.

There are some nuances which could be talked about but probably not
needed at this point.

> > 	-- One issue here is the address range for this bit is with each
> > driver in the _generic_ IP OCP (open core protocol bus interface)
> > wrapper header.  To write to this you need i+f clock on.  It still
helps
> > to set this bit even if the module is off as the clock tree can
still be
> > active and dissipating some power in the module.
> 
> You're talking about the *_SYSCONFIG autoidle bits here, right?  So to
set
> those properly we'd need to walk the clock tree, enabling module
clocks
> and setting the *_SYSCONFIG autoidle bit, then powering the module
clocks
> back down again?

Yes.
 
> > 	-- This is what the patch I sent out a while back was about
> > (RFC/PATCH) to just enable all of these.  It did save a lot of
power.
> 
> I just took another look at that patch.  The only downside is latency,
> right?  Are you thinking about updating the patch for the new PRCM
access
> code?  That would make it much easier to test...

At this level the latency should be very minimal compared to the active
power savings.  At the module level it should be on the order of a few
clocks.  With many of these clocks in the MHz range its some nano
seconds.

The danger is in cascade latency if all modules are set this way and the
upper members of the tree have their auto controls set.  The big
latencies are not at the modules (except for some in OFF mode).

Actually the patch as I sent it was completely self contained it was
done that way just to be fast :)  Changing it to use the macros is no
problem.  I'd probably shy away from using the clock frame work to turn
on and off each clock via name string though.  They would result way too
much code.

> > 	** As its generic and symmetric for every IP in the OCP wrapper
I
> > personally like to stick it all in one spot inside of adding a bunch
of
> > defines to every driver.
> 
> Since all of those registers are in SCM space, perhaps an scm.h/scm.c
file
> might be useful here.  I've been running into this with
CONTROL_DEVCONF*
> on 3430 code.  I don't think the *_SYSCONFIG powersave bits fit well
into
> the clock framework, so we should probably place it outside the
clocks.
> I do think it would make sense to specifically encode the power domain
> that each clock resides in into the struct clk, for use by PM or SCM
code.

The OCP registers are in each modules address space.  An example of what
I was talking about is GTP1.TIOCP_CFG:0x48318010.

The SCM (system control module) is something else.  It has bearing for
power in setting the right state for pins in sleep and io ring wake up.
I don't think they belong in the clock frame work either.  Though the
prcm many need to make api calls to it.

> > 	** Recently we internally were debating a bit about if an API
was
> > needed as you really in some cases do need to set the CLOCKACTIVITY
bits
> > in the OCP wrapper depending on the drivers mode of activity.
> 
> I've been looking at these CLOCKACTIVITY bits and am not clear on the
> intended use.  They are read-only in many modules, at least according
to
> the TRM.  There is a notation about "Clock activity during wakeup mode
> period" -- could you elaborate about what that means?

Well some aspects of this are a little fuzzy to me also.  However, I
know generally how they are to be used in practice.

I think of them as how the internal clocks of the module will be handled
at idle-ack time (like when the L3/L4{interconnect} clock domains go
idle, i.e. this auto ICLK handling time stuff which was being talked
about).

Internally in the module at these times the module can choose to handle
its clocks in different ways.  If you don't need 'partial' activity
(meaning functional clock working while iclock is cut) you set it up to
allow gating of both I and F clocks.  If you want partial activity you
make sure the F clock isn't module-internal modified.

One example is say a timer.  If I target a low power idle mode I can get
the interconnects to go to clock stop (Iclocks off to CORE say) but I
can set the activity on the gp-timer such that it keeps ticking -and-
can even say generate a wake up (from clock stop) interrupt which brings
the L3/L4 out of clock stop.  On say a 2430 this will have a system at
say average of 2mA but still be ticking at a HZ=100 rate from a core
domain clock.  This is compared to say a 60mA idle when not hitting
clock stop. I can telnet into a system and it is still responsive but
has really very low power.  This is distinct from system wide retention
who's currents might be in the 100uA range but nothing is functional.
Only a 'wakeup' domain interrupt will start you chip going again.  Make
sure not to mix up 'chip' retention (all domains) with just say
MPU-retention which is more or less independent of the CORE.

If during this idle time I don't' care about a particular modules I and
F clocks I can set the clockactivity bits to allow internal gating of
both I and F clocks.  The F-clock tree won't stop as some other module
might need it, but my module can gate it saving power.

On OMAP3 if you are using software control methods you may need to set
these in a particular way to ensure data has cleared before shutting
down the module.  I don't expect control at this granularity makes sense
for our typical usage, but if you are doing full hardware dependency for
idling it is relevant.

> > When ICLKEN is enabled and the PRCM-auto-idle is enabled hardware
can
> > manage that clock at domain change time assuming the peripheral
> > handshakes it ok (force/no/smart).
> >
> > If the ICLKEN is disabled the setting of PRCM-auto-idle has no
effect.
> 
> Okay, makes sense.
> 
> > One of the big target states for big power savings is this so called
> > 'partially' active state.  In this case you do want the clock
domains
> > and the power domains states to not be in sync.  The L3/L4 can be
> > stopped, but say an F-Clock to a McBSP can still be running pushing
data
> > out to a codec.  If programmed up correctly, the codec need for data
can
> > automatically signal the prcm to re-activate the L3/L4 then allow
the
> > new data to flow.
> 
> This is via the WKDEP/SLEEPDEP registers, correct?  or is this via
another
> mechanism?

No.  These registers are more targeted at reducing latency when OFF mode
is used.  They allow early power up of domains.  These are useful when
coming from inactive states not active or partially active ones.

One fun fact here is you can say set up a WKDEP such that the MPU is
powered on when something happens on say the DSP (MPU used to be in
retention).  However, if you don't have an interrupt routed to the MPU,
it will still be stuck in clock domain stop and just now be drawing more
power in ON state.  Some time later the OS timer fires and the MPU can
wake do its thing and then re-WFI back to retention.  The power draw due
to the mis-programming of the WKDEP caused extra consumption even though
the ARM wasn't doing work.  Now, if the ARM was in OFF mode, this early
power up could have saved some time.

> > However, other bits in the same range CLOCKACTIVTY do have a bit
more
> > need of dynamic access.  WE enable also might be conditionally set.
> 
> Sorry, you lost me there - what is WE enable?

I was talking about XYZ_SYSCONFIG.ENWAWAKEUP bit in OCP header.

> Thanks for all of the detailed information, Richard,

Happy to, especially if it translates to better functionality.

Regards,
Richard W.

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe clock framework
  2007-08-20 12:55   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
  2007-08-21  7:04     ` Paul Walmsley
@ 2007-08-23  9:21     ` Tuukka.Tikkanen
  2007-08-27  7:56       ` Paul Walmsley
  1 sibling, 1 reply; 41+ messages in thread
From: Tuukka.Tikkanen @ 2007-08-23  9:21 UTC (permalink / raw)
  To: r-woodruff2, paul, linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 2115 bytes --]

-----Original Message-----
> Subject: RE: [PATCH 28/28] omap2 clock: handle (almost) all clock
autoidlingviathe clock framework
> 
> Hi Paul,
> 
> > Existing OMAP2 code autoidles clocks via pm.c.  OMAP clock framework
> > already has some support for enabling autoidle mode via the
allow_idle
> > function; however, this is currently unused.  Take advantage of this
> > support by adding autoidle register and bit information for each
> > clock, defining an omap2_clk_allow_idle() function, and adding a
> > framework-wide function, clk_allow_idle_all(), to autoidle all
clocks,
> > intended to be called on init.  Remove all but the APLL/DPLL
autoidle
> > bit twiddling from pm.c -- we don't yet have generalized support for
> APLL
> > autoidle.  Handling autoidle via the clock framework ensures that we
> only
> > touch clocks that are currently configured.
> 
> I thought about doing this back when OMAP1 added this when I was more
> active on OMAP2.  However, I dropped it as it didn't have enough
'bang'
> in this form.  I think these registers (even in OMAP1) are widely
> mis-understood.  This is partially a TRM issue and one of complexity.

One minor detail to note is that on OMAP2 the sleep code sometimes has
to disable the autoidle feature on certain clocks. Not doing so would
prevent desired functionality. This - at least the action of setting the
autoidle state - of course could be handled via the clock framework.
However, it was deemed to be unnecessary extra layer, as the sleep code
already has to be very aware of the hardware its running on and any
abstraction is useless. I think at least timers and DMA have some
special restrictions in pm.c. Thus the original design of PM code
handling the autoidle bits.

Tuukka


----------------------------------------------------------------
Please note: This e-mail may contain confidential information
intended solely for the addressee. If you have received this
e-mail in error, please do not disclose it to anyone, notify
the sender promptly, and delete the message from your system.
Thank you.


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-22 21:25           ` Woodruff, Richard
@ 2007-08-27  7:39             ` Paul Walmsley
  2007-08-30 22:21               ` Woodruff, Richard
  0 siblings, 1 reply; 41+ messages in thread
From: Paul Walmsley @ 2007-08-27  7:39 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: linux-omap-open-source

Hello Richard,

On Wed, 22 Aug 2007, Woodruff, Richard wrote:

> Actually the patch as I sent it was completely self contained it was
> done that way just to be fast :)  Changing it to use the macros is no
> problem.

Cool.

> I'd probably shy away from using the clock frame work to turn on and off 
> each clock via name string though.  They would result way too much code.

Yeah, in the autoidle patch I added a clk_allow_idle_all() function that 
just walked down the clock list and called ->allow_idle() on each clock 
that had one.  This avoided the search by name string.  Nevertheless, I 
think I will set that patch aside for now, it's not critical; maybe we'll 
take another look at it after the 3430 clock code shows up.

> The OCP registers are in each modules address space.  An example of what
> I was talking about is GTP1.TIOCP_CFG:0x48318010.

Indeed, my mistake; not sure what register I was looking at when I wrote 
the earlier post.

> On OMAP3 if you are using software control methods you may need to set
> these in a particular way to ensure data has cleared before shutting
> down the module.  I don't expect control at this granularity makes sense
> for our typical usage, but if you are doing full hardware dependency for
> idling it is relevant.

Is this only if we set *_SYSCONFIG.AUTOIDLE to force-idle?


- Paul

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe clock framework
  2007-08-23  9:21     ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe " Tuukka.Tikkanen
@ 2007-08-27  7:56       ` Paul Walmsley
  2007-08-27 14:13         ` Tuukka.Tikkanen
  0 siblings, 1 reply; 41+ messages in thread
From: Paul Walmsley @ 2007-08-27  7:56 UTC (permalink / raw)
  To: Tuukka.Tikkanen; +Cc: linux-omap-open-source

On Thu, 23 Aug 2007, Tuukka.Tikkanen@elektrobit.com wrote:

> One minor detail to note is that on OMAP2 the sleep code sometimes has
> to disable the autoidle feature on certain clocks. Not doing so would
> prevent desired functionality. This - at least the action of setting the
> autoidle state - of course could be handled via the clock framework.
> However, it was deemed to be unnecessary extra layer, as the sleep code
> already has to be very aware of the hardware its running on and any
> abstraction is useless. I think at least timers and DMA have some
> special restrictions in pm.c. Thus the original design of PM code
> handling the autoidle bits.

Hi Tuukka,

I took a quick look at pm.c, it configures ICLK autoidling for SDMA and 
GPT*, and sleep.S doesn't look like it touches the autoidle regs. Could 
you point me at the code you're talking about?

thanks,

- Paul

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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe clock framework
  2007-08-27  7:56       ` Paul Walmsley
@ 2007-08-27 14:13         ` Tuukka.Tikkanen
  0 siblings, 0 replies; 41+ messages in thread
From: Tuukka.Tikkanen @ 2007-08-27 14:13 UTC (permalink / raw)
  To: paul; +Cc: linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 1837 bytes --]

 

From: paul@utopia.booyaka.com [mailto:paul@utopia.booyaka.com] On Behalf
Of Paul Walmsley
> 
> On Thu, 23 Aug 2007, Tuukka.Tikkanen@elektrobit.com wrote:
> 
> > One minor detail to note is that on OMAP2 the sleep code sometimes
has
> > to disable the autoidle feature on certain clocks. Not doing so
would
> > prevent desired functionality. This - at least the action of setting
the
> > autoidle state - of course could be handled via the clock framework.
> > However, it was deemed to be unnecessary extra layer, as the sleep
code
> > already has to be very aware of the hardware its running on and any
> > abstraction is useless. I think at least timers and DMA have some
> > special restrictions in pm.c. Thus the original design of PM code
> > handling the autoidle bits.
> 
> Hi Tuukka,
> 
> I took a quick look at pm.c, it configures ICLK autoidling for SDMA
and 
> GPT*, and sleep.S doesn't look like it touches the autoidle regs.
Could 
> you point me at the code you're talking about?

Sorry for the false alarm, guys. The code I was thinking about lives in
OMAP1 tree. The clock framework updates variable called
arm_idlect1_mask. That value is programmed after some masking into
hardware in omap_pm_idle when entering sleep state. Essentially what we
have there is a mask of clocks that may not be autoidled during that
particular idle call.

The OMAP2 tree seems to handle its special cases in another way by
skipping the sleep completely.

Tuukka


----------------------------------------------------------------
Please note: This e-mail may contain confidential information
intended solely for the addressee. If you have received this
e-mail in error, please do not disclose it to anyone, notify
the sender promptly, and delete the message from your system.
Thank you.


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* RE: [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe clock framework
  2007-08-27  7:39             ` Paul Walmsley
@ 2007-08-30 22:21               ` Woodruff, Richard
  0 siblings, 0 replies; 41+ messages in thread
From: Woodruff, Richard @ 2007-08-30 22:21 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: linux-omap-open-source

> > The OCP registers are in each modules address space.  An example of what
> > I was talking about is GTP1.TIOCP_CFG:0x48318010.
> 
> Indeed, my mistake; not sure what register I was looking at when I wrote
> the earlier post.
> 
> > On OMAP3 if you are using software control methods you may need to set
> > these in a particular way to ensure data has cleared before shutting
> > down the module.  I don't expect control at this granularity makes sense
> > for our typical usage, but if you are doing full hardware dependency for
> > idling it is relevant.
> 
> Is this only if we set *_SYSCONFIG.AUTOIDLE to force-idle?

Yes that is the bit I was talking about in this case.

Regards,
Richard W.

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

end of thread, other threads:[~2007-08-30 22:21 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-20  9:53 [PATCH 00/28] omap2 clock: framework generalization, cleanup Paul Walmsley
2007-08-20  9:53 ` [PATCH 01/28] omap2 clock: dsp_ick parent is dsp_fck, not core_ck Paul Walmsley
2007-08-20  9:53 ` [PATCH 02/28] omap2 clock: generalize initial clock rate setup: recalculate_root_clocks() Paul Walmsley
2007-08-20  9:53 ` [PATCH 03/28] omap2 clock: mark onchip_clks as __initdata Paul Walmsley
2007-08-20  9:53 ` [PATCH 05/28] omap2 clock: rename, add comment to omap2_mpu_recalc() Paul Walmsley
2007-08-20  9:53 ` [PATCH 06/28] omap2 clock: add clksel and clksel_rate data Paul Walmsley
2007-08-20  9:53 ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardware reality at clock init Paul Walmsley
2007-08-20 12:27   ` [PATCH 07/28] omap2 clock: init clksel clock parents to hardwarereality " Woodruff, Richard
2007-08-21  6:49     ` Paul Walmsley
2007-08-20  9:53 ` [PATCH 08/28] omap2 clock: convert omap2_clksel_to_divisor and omap2_divisor_to_clksel to use new clksel struct Paul Walmsley
2007-08-20  9:53 ` [PATCH 09/28] omap2 clock: convert omap2_clksel_round_rate " Paul Walmsley
2007-08-20  9:53 ` [PATCH 10/28] omap2 clock: convert omap2_get_clksel " Paul Walmsley
2007-08-20  9:53 ` [PATCH 11/28] omap2 clock: convert omap2_clksel_get_src_field() " Paul Walmsley
2007-08-20  9:53 ` [PATCH 12/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_rate() Paul Walmsley
2007-08-20  9:54 ` [PATCH 13/28] omap2 clock: stop using clk->src_offset in omap2_clk_set_parent() Paul Walmsley
2007-08-20  9:54 ` [PATCH 14/28] omap2 clock: clean out old code from omap2_clksel_recalc() Paul Walmsley
2007-08-20  9:54 ` [PATCH 15/28] omap2 clock: convert remaining clksel clocks to use omap2_clksel_recalc Paul Walmsley
2007-08-20  9:54 ` [PATCH 16/28] omap2 clock: remove all {src, rate}_offset fields from struct clk Paul Walmsley
2007-08-20  9:54 ` [PATCH 17/28] omap2 clock: use the struct clk round_rate field for clksel rate rounding code Paul Walmsley
2007-08-20  9:54 ` [PATCH 19/28] omap2 clock: drop RATE_CKCTL from all OMAP2 clocks Paul Walmsley
2007-08-20  9:54 ` [PATCH 20/28] omap2 clock: remove *_SEL* clock flags Paul Walmsley
2007-08-20  9:54 ` [PATCH 21/28] omap2 clock: call clock-specific enable/disable functions if present Paul Walmsley
2007-08-20  9:54 ` [PATCH 22/28] omap2 clock: use custom osc_ck enable/disable routines Paul Walmsley
2007-08-20  9:54 ` [PATCH 23/28] omap2 clock: use standard clk->enable/disable for APLLs Paul Walmsley
2007-08-20  9:54 ` [PATCH 24/28] omap2 clock: replace omap2_get_crystal_rate() with clock-specific recalc code Paul Walmsley
2007-08-20  9:54 ` [PATCH 25/28] omap2 clock: Standardize DPLL rate recalculation with struct dpll_data Paul Walmsley
2007-08-20  9:54 ` [PATCH 27/28] omap2 clock: add three missing clocks: gpmc_fck, sdma_{i, f}ck Paul Walmsley
2007-08-20  9:54 ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling via the clock framework Paul Walmsley
2007-08-20 12:55   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
2007-08-21  7:04     ` Paul Walmsley
2007-08-21 17:29       ` Woodruff, Richard
2007-08-22  9:49         ` Paul Walmsley
2007-08-22 21:25           ` Woodruff, Richard
2007-08-27  7:39             ` Paul Walmsley
2007-08-30 22:21               ` Woodruff, Richard
2007-08-23  9:21     ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidlingviathe " Tuukka.Tikkanen
2007-08-27  7:56       ` Paul Walmsley
2007-08-27 14:13         ` Tuukka.Tikkanen
2007-08-20 13:18   ` [PATCH 28/28] omap2 clock: handle (almost) all clock autoidling viathe " Woodruff, Richard
2007-08-20 13:30     ` Igor Stoppa
2007-08-20 13:48       ` [PATCH 28/28] omap2 clock: handle (almost) all clockautoidling " Woodruff, Richard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox