aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/clk
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-06-21 03:55:12 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-06-24 03:27:07 -0400
commit794d78fea51504bad3880d14f354a9847f318f25 (patch)
tree8515152063b174deb5af666f2ade0c4b61fec04f /drivers/sh/clk
parentbccaeafd7c117acee36e90d37c7e05c19be9e7bf (diff)
drivers: sh: late disabling of clocks V2
This V2 patch changes the clock disabling behavior during boot. Two different changes are made: 1) Delay disabling of clocks until late in the boot process. This fixes an existing issue where in-use clocks without software reference are disabled by mistake during boot. One example of this is the handling of the Mackerel serial console output that shares clock with the I2C controller. 2) Write out the "disabled" state to the hardware for clocks that not have been used by the kernel. In other words, make sure so far unused clocks actually get turned off. Signed-off-by: Magnus Damm <damm@opensource.se> Acked-by: Simon Horman <horms@verge.net.au> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh/clk')
-rw-r--r--drivers/sh/clk/core.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index 7e9c39951ecb..ebeaa9e9f068 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -34,6 +34,9 @@ static LIST_HEAD(clock_list);
34static DEFINE_SPINLOCK(clock_lock); 34static DEFINE_SPINLOCK(clock_lock);
35static DEFINE_MUTEX(clock_list_sem); 35static DEFINE_MUTEX(clock_list_sem);
36 36
37/* clock disable operations are not passed on to hardware during boot */
38static int allow_disable;
39
37void clk_rate_table_build(struct clk *clk, 40void clk_rate_table_build(struct clk *clk,
38 struct cpufreq_frequency_table *freq_table, 41 struct cpufreq_frequency_table *freq_table,
39 int nr_freqs, 42 int nr_freqs,
@@ -228,7 +231,7 @@ static void __clk_disable(struct clk *clk)
228 return; 231 return;
229 232
230 if (!(--clk->usecount)) { 233 if (!(--clk->usecount)) {
231 if (likely(clk->ops && clk->ops->disable)) 234 if (likely(allow_disable && clk->ops && clk->ops->disable))
232 clk->ops->disable(clk); 235 clk->ops->disable(clk);
233 if (likely(clk->parent)) 236 if (likely(clk->parent))
234 __clk_disable(clk->parent); 237 __clk_disable(clk->parent);
@@ -747,3 +750,25 @@ err_out:
747 return err; 750 return err;
748} 751}
749late_initcall(clk_debugfs_init); 752late_initcall(clk_debugfs_init);
753
754static int __init clk_late_init(void)
755{
756 unsigned long flags;
757 struct clk *clk;
758
759 /* disable all clocks with zero use count */
760 mutex_lock(&clock_list_sem);
761 spin_lock_irqsave(&clock_lock, flags);
762
763 list_for_each_entry(clk, &clock_list, node)
764 if (!clk->usecount && clk->ops && clk->ops->disable)
765 clk->ops->disable(clk);
766
767 /* from now on allow clock disable operations */
768 allow_disable = 1;
769
770 spin_unlock_irqrestore(&clock_lock, flags);
771 mutex_unlock(&clock_list_sem);
772 return 0;
773}
774late_initcall(clk_late_init);