diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-02-24 07:46:31 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-03 08:08:18 -0500 |
commit | 4da3782151300237db3abe070f716922889252e0 (patch) | |
tree | 5bfc719384ffecf88ad93b286afe3008f24d281c /arch/arm | |
parent | 7aec53acc0504ab2abd73a6051e7b72f48545ceb (diff) |
[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 <r-woodruff2@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 6 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 17 |
2 files changed, 10 insertions, 13 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 40cb65ba1fac..f49bce997a0b 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -807,9 +807,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) | |||
807 | if (!parent_div) | 807 | if (!parent_div) |
808 | return -EINVAL; | 808 | return -EINVAL; |
809 | 809 | ||
810 | if (clk->usecount > 0) | ||
811 | _omap2_clk_disable(clk); | ||
812 | |||
813 | /* Set new source value (previous dividers if any in effect) */ | 810 | /* Set new source value (previous dividers if any in effect) */ |
814 | v = __raw_readl(clk->clksel_reg); | 811 | v = __raw_readl(clk->clksel_reg); |
815 | v &= ~clk->clksel_mask; | 812 | v &= ~clk->clksel_mask; |
@@ -819,9 +816,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) | |||
819 | 816 | ||
820 | _omap2xxx_clk_commit(clk); | 817 | _omap2xxx_clk_commit(clk); |
821 | 818 | ||
822 | if (clk->usecount > 0) | ||
823 | _omap2_clk_enable(clk); | ||
824 | |||
825 | clk_reparent(clk, new_parent); | 819 | clk_reparent(clk, new_parent); |
826 | 820 | ||
827 | /* CLKSEL clocks follow their parents' rates, divided by a divisor */ | 821 | /* CLKSEL clocks follow their parents' rates, divided by a divisor */ |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 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) | |||
144 | return ret; | 144 | return ret; |
145 | 145 | ||
146 | spin_lock_irqsave(&clockfw_lock, flags); | 146 | spin_lock_irqsave(&clockfw_lock, flags); |
147 | if (arch_clock->clk_set_parent) | 147 | if (clk->usecount == 0) { |
148 | ret = arch_clock->clk_set_parent(clk, parent); | 148 | if (arch_clock->clk_set_parent) |
149 | if (ret == 0) { | 149 | ret = arch_clock->clk_set_parent(clk, parent); |
150 | if (clk->recalc) | 150 | if (ret == 0) { |
151 | clk->rate = clk->recalc(clk); | 151 | if (clk->recalc) |
152 | propagate_rate(clk); | 152 | clk->rate = clk->recalc(clk); |
153 | } | 153 | propagate_rate(clk); |
154 | } | ||
155 | } else | ||
156 | ret = -EBUSY; | ||
154 | spin_unlock_irqrestore(&clockfw_lock, flags); | 157 | spin_unlock_irqrestore(&clockfw_lock, flags); |
155 | 158 | ||
156 | return ret; | 159 | return ret; |