From 897dcded6fb6565f4d1c22a55d21f135403db132 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 16:35:03 +0000 Subject: [ARM] omap: provide a NULL clock operations structure ... and use it for clocks which are ALWAYS_ENABLED. These clocks use a non-NULL enable_reg pointer for other purposes (such as selecting clock rates.) Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index be6aab9c6834..529c4a9f012e 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -358,6 +358,23 @@ void clk_enable_init_clocks(void) } EXPORT_SYMBOL(clk_enable_init_clocks); +/* + * Low level helpers + */ +static int clkll_enable_null(struct clk *clk) +{ + return 0; +} + +static void clkll_disable_null(struct clk *clk) +{ +} + +const struct clkops clkops_null = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, +}; + #ifdef CONFIG_CPU_FREQ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table) { @@ -383,8 +400,10 @@ static int __init clk_disable_unused(void) unsigned long flags; list_for_each_entry(ck, &clocks, node) { - if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || - ck->enable_reg == 0) + if (ck->ops == &clkops_null) + continue; + + if (ck->usecount > 0 || ck->enable_reg == 0) continue; spin_lock_irqsave(&clockfw_lock, flags); -- cgit From eee5b19119458cd399ce4deaabea07c8d07159ae Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 21:42:54 +0000 Subject: [ARM] omap: remove clk->owner clk->owner is always NULL, so its existence doesn't serve any useful function other than bloating the kernel by 992 bytes. Remove it. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 529c4a9f012e..c53205c574d1 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -53,15 +53,14 @@ struct clk * clk_get(struct device *dev, const char *id) mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { - if (p->id == idno && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (p->id == idno && strcmp(id, p->name) == 0) { clk = p; goto found; } } list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (strcmp(id, p->name) == 0) { clk = p; break; } @@ -148,8 +147,6 @@ EXPORT_SYMBOL(clk_get_rate); void clk_put(struct clk *clk) { - if (clk && !IS_ERR(clk)) - module_put(clk->owner); } EXPORT_SYMBOL(clk_put); -- cgit From ae8fce5c3baf84e319269e67823cf337ed9d359a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 5 Nov 2008 12:54:04 +0000 Subject: [ARM] omap: remove clk_deny_idle and clk_allow_idle Nothing makes any use of these functions, so there's little point in providing them. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index c53205c574d1..7b0400728594 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -316,34 +316,6 @@ void clk_unregister(struct clk *clk) } EXPORT_SYMBOL(clk_unregister); -void clk_deny_idle(struct clk *clk) -{ - unsigned long flags; - - if (clk == NULL || IS_ERR(clk)) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_deny_idle) - arch_clock->clk_deny_idle(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_deny_idle); - -void clk_allow_idle(struct clk *clk) -{ - unsigned long flags; - - if (clk == NULL || IS_ERR(clk)) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_allow_idle) - arch_clock->clk_allow_idle(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_allow_idle); - void clk_enable_init_clocks(void) { struct clk *clkp; -- cgit From 2e777bf1f2482be13c2b678744d3497a4f0a0ec2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 8 Feb 2009 17:49:22 +0000 Subject: [ARM] omap: provide a standard clk_get_parent() implementation which only has to return clk->parent. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 7b0400728594..ae77e10719f2 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -207,18 +207,7 @@ EXPORT_SYMBOL(clk_set_parent); struct clk *clk_get_parent(struct clk *clk) { - unsigned long flags; - struct clk * ret = NULL; - - if (clk == NULL || IS_ERR(clk)) - return ret; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_get_parent) - ret = arch_clock->clk_get_parent(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; + return clk->parent; } EXPORT_SYMBOL(clk_get_parent); -- cgit From c6af45085211db8720d6b94b3985ce7198d764e3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 13:01:32 +0000 Subject: [ARM] omap: move clock propagation into core omap clock code Move the clock propagation calls for set_parent and set_rate into the core omap clock code, rather than having these calls scattered throughout the OMAP1 and OMAP2 implementations. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index ae77e10719f2..b7137c560db4 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -182,6 +182,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_rate) ret = arch_clock->clk_set_rate(clk, rate); + if (ret == 0 && (clk->flags & RATE_PROPAGATES)) + propagate_rate(clk); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -198,7 +200,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_parent) - ret = arch_clock->clk_set_parent(clk, parent); + ret = arch_clock->clk_set_parent(clk, parent); + if (ret == 0 && (clk->flags & RATE_PROPAGATES)) + propagate_rate(clk); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; -- cgit From 9a5fedac187f30116013a8420149d4ca11a44f0d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 13:44:15 +0000 Subject: [ARM] omap: move propagate_rate() calls into generic omap clock code propagate_rate() is recursive, so it makes sense to minimise the amount of stack which is used for each recursion. So, rather than recursing back into it from the ->recalc functions if RATE_PROPAGATES is set, do that test at the higher level. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index b7137c560db4..df58f5d9a5ab 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -246,8 +246,6 @@ void followparent_recalc(struct clk *clk) return; clk->rate = clk->parent->rate; - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /* Propagate rate to children */ @@ -261,8 +259,10 @@ void propagate_rate(struct clk * tclk) list_for_each_entry(clkp, &clocks, node) { if (likely(clkp->parent != tclk)) continue; - if (likely((u32)clkp->recalc)) + if (clkp->recalc) clkp->recalc(clkp); + if (clkp->flags & RATE_PROPAGATES) + propagate_rate(clkp); } } @@ -278,8 +278,12 @@ void recalculate_root_clocks(void) struct clk *clkp; list_for_each_entry(clkp, &clocks, node) { - if (unlikely(!clkp->parent) && likely((u32)clkp->recalc)) - clkp->recalc(clkp); + if (!clkp->parent) { + if (clkp->recalc) + clkp->recalc(clkp); + if (clkp->flags & RATE_PROPAGATES) + propagate_rate(clkp); + } } } -- cgit From dbb674d57b5851a4fe3122ff4280e4cf87209198 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Jan 2009 16:08:04 +0000 Subject: [ARM] omap: allow double-registering of clocks This stops things blowing up if a 'struct clk' to be passed more than once to clk_register(), which will be required when we decouple struct clk's from their names. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index df58f5d9a5ab..6b3ef2a0b04e 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -292,6 +292,12 @@ int clk_register(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; + /* + * trap out already registered clocks + */ + if (clk->node.next || clk->node.prev) + return 0; + mutex_lock(&clocks_mutex); list_add(&clk->node, &clocks); if (clk->init) -- cgit From d7e8f1f9d655af2c7ea90738bf567aa6990159b3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Jan 2009 23:03:15 +0000 Subject: [ARM] omap: convert OMAP1 to use clkdev Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6b3ef2a0b04e..6b88f7878a51 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -36,6 +36,7 @@ static struct clk_functions *arch_clock; * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ +#ifndef CONFIG_COMMON_CLKDEV /* * Returns a clock. Note that we first try to use device id on the bus * and clock name. If this fails, we try to use clock name only. @@ -72,6 +73,7 @@ found: return clk; } EXPORT_SYMBOL(clk_get); +#endif int clk_enable(struct clk *clk) { @@ -145,10 +147,12 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); +#ifndef CONFIG_COMMON_CLKDEV void clk_put(struct clk *clk) { } EXPORT_SYMBOL(clk_put); +#endif /*------------------------------------------------------------------------- * Optional clock functions defined in include/linux/clk.h -- cgit From 2b811bb56a008f0f669a1bd82e4d077e75aa059a Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 16:28:32 +0000 Subject: [ARM] omap: remove pre-CLKDEV clk_get/clk_put Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6b88f7878a51..5272a2212abd 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -36,45 +36,6 @@ static struct clk_functions *arch_clock; * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ -#ifndef CONFIG_COMMON_CLKDEV -/* - * Returns a clock. Note that we first try to use device id on the bus - * and clock name. If this fails, we try to use clock name only. - */ -struct clk * clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - int idno; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - list_for_each_entry(p, &clocks, node) { - if (p->id == idno && strcmp(id, p->name) == 0) { - clk = p; - goto found; - } - } - - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0) { - clk = p; - break; - } - } - -found: - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); -#endif - int clk_enable(struct clk *clk) { unsigned long flags; @@ -147,13 +108,6 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -#ifndef CONFIG_COMMON_CLKDEV -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); -#endif - /*------------------------------------------------------------------------- * Optional clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ -- cgit From b5088c0d90b898802318c62caf2320a53df6ce57 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Jan 2009 19:33:19 +0000 Subject: [ARM] omap: clks: call recalc after any rate change This implements the remainder of: OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c from Paul Walmsley which is not covered by the previous: [ARM] omap: move clock propagation into core omap clock code [ARM] omap: remove unnecessary calls to propagate_rate() [ARM] omap: move propagate_rate() calls into generic omap clock code commits. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 5272a2212abd..54da27af0bd5 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -140,8 +140,12 @@ int clk_set_rate(struct clk *clk, unsigned long rate) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_rate) ret = arch_clock->clk_set_rate(clk, rate); - if (ret == 0 && (clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); + if (ret == 0) { + if (clk->recalc) + clk->recalc(clk); + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + } spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -159,8 +163,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_parent) ret = arch_clock->clk_set_parent(clk, parent); - if (ret == 0 && (clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); + if (ret == 0) { + if (clk->recalc) + clk->recalc(clk); + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + } spin_unlock_irqrestore(&clockfw_lock, flags); return ret; -- cgit From 3f0a820c4c0b4670fb5f164baa5582e23c2ef118 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 31 Jan 2009 10:05:51 +0000 Subject: [ARM] omap: create a proper tree of clocks Traditionally, we've tracked the parent/child relationships between clk structures by setting the child's parent member to point at the upstream clock. As a result, when decending the tree, we have had to scan all clocks to find the children. Avoid this wasteful scanning by keeping a list of the clock's children. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 51 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 54da27af0bd5..6a1737a74477 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -143,8 +143,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -166,8 +165,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -214,24 +212,31 @@ void followparent_recalc(struct clk *clk) clk->rate = clk->parent->rate; } +void clk_reparent(struct clk *child, struct clk *parent) +{ + list_del_init(&child->sibling); + if (parent) + list_add(&child->sibling, &parent->children); + child->parent = parent; + + /* now do the debugfs renaming to reattach the child + to the proper parent */ +} + /* Propagate rate to children */ void propagate_rate(struct clk * tclk) { struct clk *clkp; - if (tclk == NULL || IS_ERR(tclk)) - return; - - list_for_each_entry(clkp, &clocks, node) { - if (likely(clkp->parent != tclk)) - continue; + list_for_each_entry(clkp, &tclk->children, sibling) { if (clkp->recalc) clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); + propagate_rate(clkp); } } +static LIST_HEAD(root_clks); + /** * recalculate_root_clocks - recalculate and propagate all root clocks * @@ -243,16 +248,18 @@ void recalculate_root_clocks(void) { struct clk *clkp; - list_for_each_entry(clkp, &clocks, node) { - if (!clkp->parent) { - if (clkp->recalc) - clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); - } + list_for_each_entry(clkp, &root_clks, sibling) { + if (clkp->recalc) + clkp->recalc(clkp); + propagate_rate(clkp); } } +void clk_init_one(struct clk *clk) +{ + INIT_LIST_HEAD(&clk->children); +} + int clk_register(struct clk *clk) { if (clk == NULL || IS_ERR(clk)) @@ -265,6 +272,11 @@ int clk_register(struct clk *clk) return 0; mutex_lock(&clocks_mutex); + if (clk->parent) + list_add(&clk->sibling, &clk->parent->children); + else + list_add(&clk->sibling, &root_clks); + list_add(&clk->node, &clocks); if (clk->init) clk->init(clk); @@ -280,6 +292,7 @@ void clk_unregister(struct clk *clk) return; mutex_lock(&clocks_mutex); + list_del(&clk->sibling); list_del(&clk->node); mutex_unlock(&clocks_mutex); } -- cgit From be5f34b77355b9b1720a88390e51441ef578720b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:09 -0700 Subject: [ARM] OMAP clock: drop clk_get_usecount() This function is race-prone and mistakenly conveys the impression to drivers that it is part of the clock interface. Get rid of it: core code that absolutely needs this can just check clk->usecount. Drivers should not use it at all. linux-omap source commit is 5df9e4adc2f6a6d55aca53ee27b8baad18897c05. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6a1737a74477..9833d73511a1 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -76,22 +76,6 @@ out: } EXPORT_SYMBOL(clk_disable); -int clk_get_usecount(struct clk *clk) -{ - unsigned long flags; - int ret = 0; - - if (clk == NULL || IS_ERR(clk)) - return 0; - - spin_lock_irqsave(&clockfw_lock, flags); - ret = clk->usecount; - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; -} -EXPORT_SYMBOL(clk_get_usecount); - unsigned long clk_get_rate(struct clk *clk) { unsigned long flags; -- cgit From 8b9dbc16d4f5786c6c930ab028722e3ed7e4285b Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Feb 2009 10:12:59 +0000 Subject: [ARM] omap: arrange for clock recalc methods to return the rate linux-omap source commit 33d000c99ee393fe2042f93e8422f94976d276ce introduces a way to "dry run" clock changes before they're committed. However, this involves putting logic to handle this into each and every recalc function, and unfortunately due to the caching, led to some bugs. Solve both of issues by making the recalc methods always return the clock rate for the clock, which the caller decides what to do with. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 9833d73511a1..08baa18497b2 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -126,7 +126,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) ret = arch_clock->clk_set_rate(clk, rate); if (ret == 0) { if (clk->recalc) - clk->recalc(clk); + clk->rate = clk->recalc(clk); propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -148,7 +148,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) ret = arch_clock->clk_set_parent(clk, parent); if (ret == 0) { if (clk->recalc) - clk->recalc(clk); + clk->rate = clk->recalc(clk); propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -188,12 +188,9 @@ static int __init omap_clk_setup(char *str) __setup("mpurate=", omap_clk_setup); /* Used for clocks that always have same value as the parent clock */ -void followparent_recalc(struct clk *clk) +unsigned long followparent_recalc(struct clk *clk) { - if (clk == NULL || IS_ERR(clk)) - return; - - clk->rate = clk->parent->rate; + return clk->parent->rate; } void clk_reparent(struct clk *child, struct clk *parent) @@ -214,7 +211,7 @@ void propagate_rate(struct clk * tclk) list_for_each_entry(clkp, &tclk->children, sibling) { if (clkp->recalc) - clkp->recalc(clkp); + clkp->rate = clkp->recalc(clkp); propagate_rate(clkp); } } @@ -234,7 +231,7 @@ void recalculate_root_clocks(void) list_for_each_entry(clkp, &root_clks, sibling) { if (clkp->recalc) - clkp->recalc(clkp); + clkp->rate = clkp->recalc(clkp); propagate_rate(clkp); } } -- cgit From 4da3782151300237db3abe070f716922889252e0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 24 Feb 2009 12:46:31 +0000 Subject: [ARM] omap: clk_set_parent: deny changing parent if clock is enabled Richard Woodruff writes: | The historic usage of this has been against single use leaf clocks | (1st instance of gptimer). When it was used it did: | clk_get() | clk_set_parent() | clk_enable() | | This usage was ok for that. Use on a disabled clock is needed. | | If there are multiple users on the clock or it is enabled there are | problems. | | The call can still be unfriendly if 2 different drivers are using the | clock with their own clock get/enable. It might be the function should | return an error if usecount != 0 to stop surprises. It is all around | better if the parenting is done when the clock is off. This is a good reason to ensure that the clock is not enabled when clk_set_parent() is called. Acked-by: Richard Woodruff Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'arch/arm/plat-omap/clock.c') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 08baa18497b2..2e0614552ac8 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -144,13 +144,16 @@ int clk_set_parent(struct clk *clk, struct clk *parent) return ret; spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_set_parent) - ret = arch_clock->clk_set_parent(clk, parent); - if (ret == 0) { - if (clk->recalc) - clk->rate = clk->recalc(clk); - propagate_rate(clk); - } + if (clk->usecount == 0) { + if (arch_clock->clk_set_parent) + ret = arch_clock->clk_set_parent(clk, parent); + if (ret == 0) { + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + } + } else + ret = -EBUSY; spin_unlock_irqrestore(&clockfw_lock, flags); return ret; -- cgit